【问题标题】:Optimizing queries vs. adding indexes优化查询与添加索引
【发布时间】:2015-10-19 19:37:01
【问题描述】:

我正在尝试优化这个非常古老且缓慢的查询,但我不确定我是否可以对它做任何事情,但在 WHERE、JOIN 和 ORDER BY 所涉及的列上添加更多索引。

查询:

SELECT TOP 400 jobticket.jobnumber, jobticket.typeform, jobticket.filename, jobticket.req_number, jobticket.reqd_del_date, jobticket.point_of_contact, jobticket.status, jobticket.DapsDate, jobticket.elpod, job_info.IDOrderMaskedStatus, job_info.job_status, job_info.SalesID, job_info.location, job_info.TOMetadataID 
FROM jobticket WITH (NOLOCK) 
INNER JOIN job_info WITH (NOLOCK) ON job_info.jobnumber = jobticket.jobnumber 
WHERE  
(
    NOT(
        (jobticket.status = 'Complete' OR jobticket.status = 'Completed') 
         and (job_info.job_status = 'Actualized' OR job_info.job_status = '' 
              OR job_info.job_status = 'Actualized Credit Billed' 
              OR job_info.job_status = 'DWAS Actualized' OR job_info.job_status = 'DWAS Actualized Credit Billed'
             )
        )  
    or 
    ((SELECT COUNT(job_status) AS Expr1 FROM tblConsolidatedBilling AS tblConsolidatedBilling_1 WITH (NOLOCK)  
      WHERE  (job_status <> 'Actualized' 
      AND  job_status <> 'Actualized Credit Billed') 
      AND (master_jobnumber = jobticket.jobnumber)) > 0) 
) 
and (jobticket.status != 'Waiting Approval' or (jobticket.status = 'Waiting Approval' and jobticket.DPGType is null))  
and jobticket.typeform <> 'todpg'  
and ((job_info.isHidden <> 1 or job_info.isHidden is null) and job_info.isInConcurrentRelease is null)  
and job_info.deleted != '1' 
and jobticket.status != 'New Job'  
and jobticket.status != 'PRFYCLSFD'  

ORDER BY 
job_info.expediencyLevel DESC, 
jobticket.jobnumber DESC

执行计划:

老实说,我不知道如何处理这个查询。

是否应该在 WHERE JOIN 和 ORDER BY 中涉及的所有列上添加单独的非聚集索引?

这些表上有很多索引,但我不确定它们对这个查询是否有帮助:

【问题讨论】:

  • 您是否以某种方式根据数据库优化顾问结果自动创建索引?或者你怎么会有这么多重复的索引...
  • 我不知道。我正在努力收拾烂摊子:)

标签: sql-server query-optimization sql-execution-plan


【解决方案1】:

查看此 SQL,我并没有真正看到用于获取行的任何明确标准。看起来它只是排除了许多具有不同标准的行。我的猜测是,票证通常最终处于大多数行都存在的状态,而这些行不包含在结果中?

问题在于,它实际上并没有任何明确的标准,而且它有很多不同的规则,所以这就是为什么它最终对所有行进行聚集索引扫描 + 键查找.扫描从jobinfo开始,但我不确定如果从jobticket开始会不会有什么不同。

删除大部分索引可能是一个不错的起点,但它根本不会加快选择速度。

查询看起来很复杂,所以我猜您无法创建包含这些数据的索引视图。假设此查询经常执行并且数据没有发生太大变化(并且维护大量索引的开销将被删除),这可能会有所帮助,但这可能是不可能的。

另一个想法是研究何时可以排除行的规则,是否有可能对此有更明确的规则,因此可以对其进行索引,也许可以通过在表中添加一个持久计算列。

您没有提到这实际上需要多长时间,以及表格中有多少行,所以一切基本上只是猜测。在问题中包含更多数据+统计信息输出可能会有所帮助。

ps。我个人不推荐使用 NOLOCK,除非在非常特殊的情况下,因为它会导致非常难以解决的问题,例如多次读取相同的数据或完全跳过行。

【讨论】:

  • 对于索引视图,如果您可以创建一个连接 jobinfo 和 jobticket 的视图,它甚至可能会有所帮助,因为我的猜测是连接这些表 + 键查找是缓慢的原因。
  • 如果索引视图不起作用,某些过滤索引肯定会有所帮助。正如您所提到的,主要的痛点是过滤条件的明确隔离。对过滤器的乐观方法可能比悲观方法产生更快的响应。也许像将 JobInfo 过滤器移动到 Join 本身而不是 where 条件可能有帮助这样简单。
  • @BradD 将 JobInfo 过滤器移入 JOIN 是什么意思?
  • @Angelina - 我猜 JobInfo 表在垂直方向上相当大。您的查询是结构化的,以便您返回整个 JobInfo 表,然后通过 where 过滤器对其进行删减。所以不要说 SELECT...FROM...JOIN... WHERE...(JobInfo/Ticket criteria) 这样做; SELECT... FROM...JOIN(JobInfo 标准)...WHERE(JobTicket 标准)
【解决方案2】:

一个简单的解决方法是让 job_info 和 tblConsolidatedBilling 上的索引覆盖,因为那里的关键查找花费了大量时间。这应该给出一个整数因子加速。如果这还不够,我们需要进一步调查。

【讨论】:

  • 我应该为 job_info 和 tblConsolidatedBilling 表中的每一列创建索引吗?
  • 每个表都应该接收一个索引,该索引包含此查询所需的所有列。
猜你喜欢
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
  • 1970-01-01
  • 1970-01-01
  • 2012-11-26
  • 2018-11-30
  • 2014-05-20
相关资源
最近更新 更多