使用子查询和联接的SQL查询性能

时间:2018-07-18 20:02:57

标签: sql sql-server

我需要加快以下查询的执行时间,因为执行时间太长,我认为子查询就是问题

SELECT WFApplication.*,
       WorkflowIncidentType.TypeName ProcessCategory,
       WFProcess.WFProcessName ProcessName,
       LUTAppStatus.EnglishName AppStatus
FROM WFApplication
INNER JOIN LUTAppStatus ON WFApplication.ApplicationStatus = LUTAppStatus.Id
INNER JOIN WorkflowIncidentType ON WorkflowIncidentType.TypeID = WFApplication.ApplicationIncidentType
INNER JOIN WFProcess ON WFProcess.WFProcessId = WFApplication.ApplicationProcess
LEFT OUTER JOIN IBSCustomer ON IBSCustomer.RIM = WFApplication.RIM
LEFT OUTER JOIN Reschedule ON Reschedule.RescheduleId = WFApplication.ProcessId
WHERE WFApplication.ProcessId IN
    (SELECT ProcessId
     FROM WFProcessInstanceLog)
  AND WFProcessInstanceId IN (28251,
                              28345,
                              28773,
                              28774,
                              28846,
                              29309, .....) 

2 个答案:

答案 0 :(得分:2)

好的,这是查询SQL性能优化的基础。

第一步:显示实际执行计划。在“查询”菜单中,选中“包括实际执行计划”。然后,当您运行查询时,结果窗格中将显示一个额外的标签,用于“执行计划”。

第二步:查看树中最右边的节点。通常会有四种可能性:

  • 表扫描。基本上,这很糟糕。这表明必须浏览整个表才能找到它要查找的内容-根本不用索引。如果桌子很小,那可能没什么大不了的。如果桌子很大,那么您可能有问题。
  • 集群索引扫描。也很糟糕。聚集索引表,因此,如果SQL正在通过一个表进行扫描,则意味着它在整个表中进行扫描。
  • 索引扫描-非群集。半不正确。基本上,它 能够使用索引来帮助查看数据(而不是完整的表),但是它无法使用Binary Finds快速缩小其查找的数据范围。
  • 索引搜索(非集群或集群)-您要执行的操作。这意味着SQL能够快速找到所需数据的二进制方式。

现在,是什么原因导致SQL选择一个选项而不是另一个?首先重要的是您的索引。通常,“执行计划”会提醒您缺少索引,这些索引会提高查询的性能。但是您可以手动查看-如果使用完整扫描正在通过“表A” ...为什么?查找,搜索或匹配哪个列?很有可能,该列需要有一个索引,以便引擎可以快速对其进行匹配。

但是还有其他原因。可以说表没有那么大,并且您要在表上匹配很多条目。对于SQL来说,仅浏览整个表可能会更快。

另一个经常被忽略的原因:您在相关列上有索引,但是它们没有将数据缩小到足以使它们有价值的地步-或者,它正在查看许多不同的索引以试图纠缠它们与原始表相比,所有操作都比仅使用大型表慢。在这种情况下,解决方案是创建索引中包含多个列的索引。

诊断此类问题的一种好方法是忽略某些表/数据,并查看执行计划是否发生了变化。例如,尝试以下查询:

SELECT WFApplication.*
FROM WFApplication
WHERE WFProcessInstanceId IN (28251,
                          28345,
                          28773,
                          28774,
                          28846,
                          29309, .....)

执行计划是否更改?如果以上语句中的计划不正确,则可能意味着您缺少WFProcessInstanceId上的索引,或者您的表不足以对主表提供5000个引用。

但是,如果它在该查询上使用索引查找,但是在添加其他表时切换到“扫描”操作,则可能表明您需要将这些其他查找列添加到单独的表中索引,这样就不必尝试协调多个索引。

答案 1 :(得分:0)

如果这是子查询,则可以在wfapplication和wfprocessingstancelog之间进行内部联接。没有充分的理由为此使用子查询:

SELECT WFApplication.*,
       WorkflowIncidentType.TypeName ProcessCategory,
       WFProcess.WFProcessName ProcessName,
       LUTAppStatus.EnglishName AppStatus
FROM WFApplication
Inner Join WFProcessInstanceLog WPL on WPL.ProcessID = WFApplicaiton.ProcessId
INNER JOIN LUTAppStatus ON WFApplication.ApplicationStatus = LUTAppStatus.Id
INNER JOIN WorkflowIncidentType ON WorkflowIncidentType.TypeID = WFApplication.ApplicationIncidentType
INNER JOIN WFProcess ON WFProcess.WFProcessId = WFApplication.ApplicationProcess
LEFT OUTER JOIN IBSCustomer ON IBSCustomer.RIM = WFApplication.RIM
LEFT OUTER JOIN Reschedule ON Reschedule.RescheduleId = WFApplication.ProcessId
WHERE WFProcessInstanceId IN (28251,
                              28345,
                              28773,
                              28774,
                              28846,
                              29309, .....)