Perché il numero di esecuzioni della scansione dell'indice cluster è così elevato?


15

Ho due query simili che generano lo stesso piano di query, tranne per il fatto che un piano di query esegue una scansione dell'indice cluster 1316 volte, mentre l'altro lo esegue 1 volta.

L'unica differenza tra le due query sono criteri di data diversi. La query di lunga durata in realtà riduce i criteri di data e tira indietro meno dati.

Ho identificato alcuni indici che aiuteranno con entrambe le query, ma voglio solo capire perché l'operatore Clustered Index Scan sta eseguendo 1316 volte su una query praticamente identica a quella in cui viene eseguita 1 volta.

Ho controllato le statistiche sul PK in fase di scansione e sono relativamente aggiornate.

Query originale:

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

Genera questo piano: inserisci qui la descrizione dell'immagine

Dopo aver ristretto i criteri dell'intervallo di date:

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

Genera questo piano: inserisci qui la descrizione dell'immagine


Potresti copiare / incollare le tue query in un blocco di codice anziché in file di immagine?
Eric Humphrey - lotsahelp il

Sicuro: ho aggiunto le query che stanno generando ogni piano.
Seibar,

Su quale tabella si sta verificando la scansione dell'indice cluster?
Eric Humphrey - lotsahelp il

La scansione dell'indice cluster si trova nella sottoquery nell'unione di sinistra (PostNFIRSSummary)
Seibar

1
Presumibilmente l'ultima volta che le statistiche sono state aggiornate, c'era solo zero o una riga che soddisfaceva i FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'criteri e da allora c'è stato un numero sproporzionato di inserti in quell'intervallo. Si stima che saranno necessarie solo 1,07 esecuzioni per quell'intervallo di date. Non i 1.316 che ne conseguono nella realtà.
Martin Smith,

Risposte:


9

Il JOIN dopo la scansione fornisce un indizio: con meno righe su un lato dell'ultimo join (leggendo da destra a sinistra ovviamente) l'ottimizzatore sceglie un "loop nidificato" e non un "hash join".

Tuttavia, prima di guardare a questo, vorrei eliminare Key Lookup e DISTINCT.

  • Ricerca chiave: il tuo indice su FIR_Incident dovrebbe coprire, probabilmente (FI_IncidentDate, incidentid)o viceversa. O avere entrambi e vedere quale viene utilizzato più spesso (entrambi possono essere)

  • Il DISTINCTè una conseguenza del LEFT JOIN ... IS NOT NULL. L'ottimizzatore lo ha già rimosso (i piani hanno "lasciato semi join" sul JOIN finale) ma userò EXISTS per chiarezza

Qualcosa di simile a:

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'

Puoi anche utilizzare le guide di piano e i suggerimenti JOIN per fare in modo che SQL Server utilizzi un hash join, ma prima prova a farlo funzionare normalmente: una guida o un suggerimento probabilmente non supereranno la prova del tempo perché sono utili solo per i dati e query che esegui ora, non in futuro

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.