SQL Server 昂贵的嵌套循环连接和惰性表假脱机

Fza*_*Fza 4 performance sql-server t-sql execution-plan sql-server-2016 query-performance

我正在尝试调整以下查询,无论将什么值作为参数传入,该查询都需要 15-16 秒,查询是:

select distinct d.documentpath as path, d.documentname as name, d.datecreated as created, pc.DateProcessed
from datagatheringruntime dgr 
 inner join processentitymapping pem on pem.entityid = dgr.entityid 
 inner join document d on d.entityid = pem.entityid or d.unitofworkid = pem.processid
 left join PendingCorrespondence pc on pc.PendingCorrespondenceId = d.PendingCorrespondenceId
 where rootid = @P0 and dgr.name in('cust_pn', 'case_pn')
OPTION(RECOMPILE)
Run Code Online (Sandbox Code Playgroud)

我已经更新了查询涉及的所有表的统计信息(不包括DataGatheringRuntime在 ~ 处相当大的表100GB),并尝试使用 a 重新分解查询,CTE但获得相同的执行计划并需要一些帮助。

实际的执行计划可以在这里找到:

https://www.brentozar.com/pastetheplan/?id=ByUVIqlFE

这是从执行计划明确指出,问题在于对外部输入nested loop join与特别是lazy table spool以下的scan非群集的IX_Camunda_1上的索引Document表,但我不知道如何解决这个问题,并希望任何指导。

在此处输入图片说明

Ran*_*gen 5

我会尝试删除和OR之间的连接中的子句documentprocessingentitymapping

你可以这样做 UNION

SELECT distinct d.documentpath as path, d.documentname as name, d.datecreated as created, pc.DateProcessed
FROM datagatheringruntime dgr 
INNER JOIN processentitymapping pem on pem.entityid = dgr.entityid 
INNER JOIN document d on d.entityid = pem.entityid 
LEFT JOIN PendingCorrespondence pc on pc.PendingCorrespondenceId = d.PendingCorrespondenceId
WHERE rootid = @P0 and dgr.name in('cust_pn', 'case_pn')
UNION
SELECT distinct d.documentpath as path, d.documentname as name, d.datecreated as created, pc.DateProcessed
FROM datagatheringruntime dgr 
INNER JOIN processentitymapping pem on pem.entityid = dgr.entityid 
INNER JOIN document d on d.unitofworkid = pem.processid
LEFT JOIN PendingCorrespondence pc on pc.PendingCorrespondenceId = d.PendingCorrespondenceId
WHERE rootid = @P0 and dgr.name in('cust_pn', 'case_pn')
OPTION(RECOMPILE);
Run Code Online (Sandbox Code Playgroud)

原因是工作台线轴正在给NESTED LOOPS操作员 喂食在此处输入图片说明

在这个嵌套循环运算符上是OR谓词。 在此处输入图片说明

过滤直到我们剩下 9 行。

将 更改OR为 aUNION应该删除线轴,您可能需要在删除OR.

重写后可以提高性能的索引 UNION

CREATE INDEX IX_EntityId
on document(EntityId)
INCLUDE(DocumentPath, DocumentName, DateCreated, PendingCorrespondenceId);

CREATE INDEX IX_UnitOfWorkId
on document(UnitOfWorkId)
INCLUDE(DocumentPath, DocumentName, DateCreated, PendingCorrespondenceId);
Run Code Online (Sandbox Code Playgroud)

有关此问题的另一个示例,请参见此处