Pourquoi le nombre d'exécutions d'indexation en cluster est-il si élevé?

15

J'ai deux requêtes similaires qui génèrent le même plan de requête, sauf qu'un plan de requête exécute un balayage d'index en cluster 1316 fois, tandis que l'autre l'exécute 1 fois.

La seule différence entre les deux requêtes réside dans des critères de date différents. La requête de longue durée réduit en fait les critères de date et recule moins de données.

J'ai identifié certains index qui aideront avec les deux requêtes, mais je veux juste comprendre pourquoi l'opérateur Clustered Index Scan exécute 1316 fois sur une requête qui est pratiquement la même que celle où il s'exécute 1 fois.

J'ai vérifié les statistiques sur le PK en cours d'analyse, et elles sont relativement à jour.

Requête d'origine:

select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
    select incident_id as exported_incident_id
    from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-06-01 00:00:00.000' and '2011-07-01 00:00:00.000'
    and exported_incidents.exported_incident_id is not null

Génère ce plan: entrez la description de l'image ici

Après avoir réduit les critères de plage de dates:

select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
    select incident_id as exported_incident_id
    from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'
    and exported_incidents.exported_incident_id is not null

Génère ce plan: entrez la description de l'image ici

Seibar
la source
Pourriez-vous copier / coller vos requêtes dans un bloc de code au lieu de fichiers image?
Eric Humphrey - lotsahelp
Bien sûr - j'ai ajouté les requêtes qui génèrent chaque plan.
Seibar
Sur quelle table l'analyse d'index en cluster se produit-elle?
Eric Humphrey - lotsahelp
L'analyse d'index cluster est sur la sous-requête dans la jointure gauche (PostNFIRSSummary)
Seibar
1
On peut supposer que la dernière fois que les statistiques ont été mises à jour, il n'y avait que zéro ou une ligne répondant aux FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'critères et depuis lors, il y a eu un nombre disproportionné d'insertions dans cette plage. Il estime que seulement 1,07 exécution sera nécessaire pour cette plage de dates. Pas les 1316 qui s'ensuivent dans la réalité.
Martin Smith

Réponses:

9

Le JOIN après l'analyse donne un indice: avec moins de lignes d'un côté de la dernière jointure (lecture de droite à gauche bien sûr), l'optimiseur choisit une "boucle imbriquée" et non une "jointure de hachage".

Cependant, avant de regarder cela, je visais à éliminer la recherche de clé et le DISTINCT.

  • Recherche de clé: votre index sur FIR_Incident devrait couvrir, probablement (FI_IncidentDate, incidentid)ou l'inverse. Ou avoir les deux et voir lequel est utilisé le plus souvent (les deux peuvent l'être)

  • Le DISTINCTest une conséquence du LEFT JOIN ... IS NOT NULL. L'optimiseur l'a déjà supprimé (les plans ont "laissé des semi-jointures" sur le JOIN final) mais j'utiliserais EXISTS pour plus de clarté

Quelque chose comme:

select 
    F.IncidentID
from 
    FIR_Incident F
where 
    exists (SELECT * FROM postnfirssummary P
           WHERE P.incident_id = F.incidentid)
    AND
    F.FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'

Vous pouvez également utiliser des guides de plan et des conseils JOIN pour que SQL Server utilise une jointure de hachage, mais essayez de le faire fonctionner d'abord: un guide ou un conseil ne résistera probablement pas à l'épreuve du temps car ils ne sont utiles que pour les données et les requêtes que vous exécutez maintenant, pas à l'avenir

gbn
la source