web-dev-qa-db-fra.com

SQL Server Cher imbriquée des boucles imbriquées et une bobine de table paresseuse

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.

enter image description here

4
Fza

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 enter image description here

Et sur cet opérateur de boucles imbriqués est le prédicat OR. enter image description here

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

4
Randi Vertongen

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 )
0
KumarHarsh