2013-02-08 17 views
6

Considerare questi tre quesiti:Perché le prestazioni diminuiscono quando si utilizza un campo non indicizzato nella clausola SELECT?

select sampleno from sample 
    where markupdate > '1/1/2010' 

select sampleno, markupdate from sample 
    where markupdate > '1/1/2010' 

select sampleno, markuptime from sample 
    where markupdate > '1/1/2010' 

sampleno e markupdate campi sono indicizzati (sampleno è la chiave primaria)

markuptime non è indicizzato

Query 1 e 2 richiede circa 1 secondo per eseguire (restituendo 237K righe). Query 3 è ancora in esecuzione dopo 3 minuti.

Perché l'inclusione di un campo non indicizzato nella clausola SELECT causa un tale peggioramento delle prestazioni?

Questo è un database SQL 6.5.

risposta

5

I dati di una tabella (in pratica: tutte le colonne) sono memorizzati in un indice cluster . Un indice cluster è un albero binario che consente una ricerca binaria sulle colonne indicizzate. È speciale (in cluster) in quanto contiene tutte le altre colonne a livello foglia. Di solito, l'indice cluster è anche la chiave primaria. Nel tuo caso, si tratta di:

(sampleno) include (markupdate, markuptime, ...) 

A indice non cluster contiene la colonna indicizzata (s) e (al livello foglia) l'indice cluster. Quando si utilizza un indice non cluster, il database deve cercare tutte le altre colonne dell'indice cluster. Tale processo è chiamato ricerca . Nel tuo caso, l'indice non cluster in (markupdate) è:

(markupdate) include (sampleno) 

Questo indice contiene tutti i dati per una query su markupdate, sampleno. Il termine tecnico per tale indice è un indice che copre. Ma quando si aggiunge markuptime alla query, l'indice non copre più. Deve cercare il valore per markuptime nell'indice cluster. E le ricerche sono espansive.

Solo la terza query richiede ricerche. Ed è per questo che la terza query è più lenta.

+0

C'è qualcosa che posso fare alla query per includere temporaneamente markuptime in un indice o devo creare un indice per la tabella che include markuptime? – blueshift

+1

Puoi aggiungere un INCLUDE per includere MarkupTime sul tuo indice non in cluster su MarkUpdate, questo ti darà un "indice di copertura" per la terza query. (Non importa, potresti farlo se avessi una versione più recente di SQL ... Immagino di aggiungere MarkupTime come un'altra colonna all'indice MarkUpdate.) –

Problemi correlati