J'essaie d'accorder la requête ci-dessous qui prend 15-16 secondes, quelle que soit la valeur transmise sous forme de paramètre, la requête est la suivante:
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)
J'ai mis à jour les statistiques de toutes les tables touchées par la requête (à l'exclusion de la table DataGatheringRuntime
qui est assez importante à ~ 100GB
) Et avez essayé de réexprimer la requête en utilisant un CTE
mais obtenez le même plan d'exécution et avez besoin d'une assistance.
Le plan d'exécution actuel peut être trouvé ici:
https://www.brentozar.com/pasetheplan/?id=byuviqlfe
Il ressort clairement du plan d'exécution que le problème réside avec l'entrée extérieure sur le nested loop join
Spécifiquement avec le lazy table spool
Suivre le scan
du non-clustered IX_Camunda_1
Index sur la table Document
, mais je ne sais pas comment aborder cette question et apprécierait des conseils.
J'essaierais de supprimer la clause OR
dans la jointure entre document
et processingentitymapping
Vous pourriez faire cela avec 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);
La raison étant que la bobine de la table alimente le NESTED LOOPS
opérateur
Et sur cet opérateur de boucles imbriqués est le prédicat OR
.
Filtrer jusqu'à ce que nous ayons 9 rangs restants.
Changer le OR
à un UNION
doit supprimer la bobine, vous devrez peut-être examiner l'indexation après avoir retiré le OR
.
index pouvant améliorer les performances après la réécriture avec 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);
voir ici pour un autre exemple sur cette
Au lieu de traitement DataGatheringRuntime table which is quite big at ~100GB)
Temps Times Thems Traitez la seule fois en les mettant en #temp
tableau ou CTE
Ensuite, supprimez Distinct
. S'il y a des données en double, trouvez la raison derrière les données en double et supprimez les données en double en écrivant une requête correcte.
Quel est le but de Distinct
et UNION
dans la même requête?
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 )