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:
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:
la source
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é.Réponses:
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
DISTINCT
est une conséquence duLEFT 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:
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
la source