パラメータとして渡される値に関係なく、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)
_
クエリに関連するすべてのテーブル(〜_100GB
_で非常に大きいDataGatheringRuntime
テーブルを除く)の統計を更新し、CTE
を使用してクエリをリファクタリングしようとしましたが、同じ実行プランを取得していくつか必要です援助。
実際の実行計画はここにあります:
https://www.brentozar.com/pastetheplan/?id=ByUVIqlFE
問題は_nested loop join
_の外部入力にあり、特にscan
テーブルの非クラスター化_lazy table spool
_インデックスのDocument
に続く_IX_Camunda_1
_に問題があることは明らかですが、その問題に取り組む方法がわからないので、ガイダンスをいただければ幸いです。
OR
とdocument
の間の結合からprocessingentitymapping
句を削除してみます
あなたは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);
その理由は、テーブルスプールがNESTED LOOPS
演算子
残りの9行になるまでフィルタリングします。
OR
をUNION
に変更すると、スプールが削除されます。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);
ここを参照 これに関する別の例
処理する代わりにDataGatheringRuntime table which is quite big at ~100GB)
mutiples回は、それらを#temp
テーブル またはCTE
次に、Distinct
を削除します。重複データがある場合は、重複データの背後にある理由を見つけ、正しいクエリを作成して重複データを削除します。
同じクエリでのDistinct
とUNION
の目的は何ですか?
Create table #temp(entityid int,processid int)
select pem.entityid,pem.processid
from datagatheringruntime dgr
inner join processentitymapping pem on pem.entityid = dgr.entityid
where rootid = @P0 and dgr.name in('cust_pn', 'case_pn')
--OPTION(RECOMPILE)
select d.documentpath as path, d.documentname as name, d.datecreated as created, pc.DateProcessed
from document d
left join PendingCorrespondence pc on pc.PendingCorrespondenceId = d.PendingCorrespondenceId
where exists(select 1 from #temp pem where d.entityid = pem.entityid )
UNION ALL
select d.documentpath as path, d.documentname as name, d.datecreated as created, pc.DateProcessed
from document d
left join PendingCorrespondence pc on pc.PendingCorrespondenceId = d.PendingCorrespondenceId
where exists(select 1 from #temp pem where d.unitofworkid = pem.processid )