Perché la creazione di questo nuovo indice ha migliorato così tanto le prestazioni quando l'indice esistente includeva tutte le colonne nel nuovo indice?


19

Ho tabelle Log e LogItem; Sto scrivendo una query per ottenere alcuni dati da entrambi. Ce ne sono migliaia Logse ognuna Logpuò avere fino a 125LogItems

La query in questione è complicata, quindi la sto saltando (se qualcuno pensa che sia importante probabilmente la posso pubblicare), ma quando ho eseguito il piano Query stimata SSMS, mi ha detto che un nuovo indice non cluster migliorerebbe le prestazioni fino al 100% .

Existing Index: Non-clustered
Key Colums (LogItem): ParentLogID, DateModified, Name, DatabaseModified

Query Plan Recommendation
CREATE NONCLUSTERED INDEX [LogReportIndex]
ON [dbo].[LogItem] ([ParentLogID],[DatabaseModified])

Solo per divertimento, ho creato questo nuovo indice ed eseguito la query e con mia grande sorpresa, ora ci vogliono ~ 1 secondo per l'esecuzione della mia query, quando prima erano più di 10 secondi.

Ho ipotizzato che il mio indice esistente avrebbe coperto questa nuova query, quindi la mia domanda è: perché la creazione di un nuovo indice sulle sole colonne utilizzate nella mia nuova query ha migliorato le prestazioni? Dovrei avere un indice per ogni combinazione unica di colonne utilizzate nelle mie whereclausole?

nota: non penso che ciò sia dovuto al fatto che SQL Server memorizza i miei risultati nella cache, ho eseguito la query circa 25-30 volte prima di creare l'indice e ci sono voluti costantemente 10-15 secondi, dopo che l'indice è ora costantemente ~ 1 o meno.


Prima di creare l'indice aggiuntivo non cluster, che cosa mostrava il piano di esecuzione effettivo per l'utilizzo dell'indice?
Thomas Stringer,

Che cos'è il miglioramento delle prestazioni del 100%?

@Shark Bella domanda, non ne sono sicuro. Questa è la mia prima situazione di debug delle prestazioni. Sarò sicuro di prenderlo andando avanti. Tutto ciò che diceva era "Indice mancante" e diceva quali campi.

@JeffO Questo è quanto affermato da SSMS: "Il processore di query stima che l'implementazione del seguente indice potrebbe migliorare il costo della query del 100%".

Risposte:


21

L'ordine delle colonne in un indice è importante. Se il filtro richiede le colonne 1 e 4 dall'indice, l'indice non è di aiuto. È utile solo quando si filtra per le prime N colonne consecutive.

Questo perché index è un albero. Non è possibile selezionare in modo efficiente tutti i nodi dell'albero dove column3 = something, poiché sono sparsi in tutti gli altri luoghi, appartenenti a valori diversi di column1e column2. Ma se lo sai column1e column2anche, individuare il ramo giusto nell'albero non è un gioco da ragazzi.


Sarebbe quindi sicuro supporre (in generale) che ho bisogno di un indice per serie di clausole "where" che andranno a colpire quella tabella?

Una volta ho fatto un'enorme accelerazione della query di qualcun altro solo assicurandomi che usasse l'indice nell'ordine corretto.

1
@Nate in generale, sì. Alcuni wheres possono sovrapporsi, quindi potresti avere un indice che copre bene diversi wheres; oppure puoi ignorare alcune parti di una whereclausola perché l'indicizzazione su una determinata colonna non aiuta comunque (bassa selettività); ma in generale sì.

@Nate Non vuoi avere più indici del necessario. Ogni indice che SQL deve mantenere aggiunge un overhead proprio. Se riesci a riordinare le clausole WHERE in modo che corrispondano alle prime N colonne su un indice esistente, ciò dovrebbe avvicinarti molto senza aggiungere ulteriori indici.
Quel Chuck Guy il

1
@ChuckBlumreich L'ordine delle colonne nelle whereclausole non è importante. Il server li organizzerà sempre per sfruttare al meglio gli indici esistenti. È solo una questione di avere un indice che include tutte le wherecolonne richieste come prime colonne.

12

Il vantaggio di un indice è ciò che conta.

Finché la query è "coperta" da un bordo di un indice, sarà efficiente. Gli indici del database sono in genere implementati come alberi B e la struttura dell'albero B indica che la ricerca deve essere eseguita in un determinato ordine, motivo per cui l'ordine dei campi nell'indice composito è importante.

Se hai "buchi", ad esempio se cerchi ParentLogIDe DatabaseModified, ma hai solo l'indice acceso {ParentLogID, DateModified, Name, DatabaseModified}, solo la {ParentLogID}parte dell'indice può essere utilizzata in modo efficiente.

(NOTA: alcuni DBMS possono utilizzare la {DatabaseModified}porzione tramite "skip scan", ma anche se il tuo DBMS lo fa è molto meno efficiente del normale accesso all'indice) .


Quindi se ho Columns (a, b, c, d, e, f)e la maggior parte delle query è il ... WHERE A IN(...) AND B = 3mio indice Index(a,b,c,d)che è buono, ma non aiuta se ho ... WHERE A IN (...) AND D = 5qual è il motivo per cui il mio nuovo indice che ho creato, Index(a,d)migliorato le prestazioni così tanto, giusto?

8
@Nate: corretto. Pensala come una rubrica. Se conosci solo il nome di qualcuno, è impossibile trovare senza consultare l'intero libro poiché è organizzato su Cognome, Nome
JNK
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.