2011-11-29 17 views
7
SELECT X.ID, X.Field4 
FROM 
     #TaxInvoiceData T 
INNER JOIN 
     xxx X 
     ON T.Id = X.Id 
     AND Field2 = @VAR  
     AND Field3 = 'S' 

Quando eseguo una query una tabella completa scansione sulla tabella X. Non capisco perché, perché la chiave primaria della tabella X èPerché viene eseguita una scansione della tabella?

ID INT ASC 
Field3 CHAR(2) ASC 
Field2 DATETIME ASC Unique Non-clustered 

C'è anche un indice sulla

Field2 DATETIME ASC Non-Unique Non-clustered 

fare proprio

SELECT ID 
FROM xxx 
WHERE 
    Field2 = @VAR 
AND Field3 = 'S' 

Esiste un Index Seek

Grazie in anticipo.

+0

Quante righe sono in #TaxInvoiceData? – Joe

+0

* Ricerca indice * - ok, ma su ** quale indice ** ??? Inoltre: tu dici '(ID, Field2, Field3)' sono la chiave primaria sul tuo 'Table X' - è che ** l'indice cluster ** sul tavolo, anche ?? O questo è un mucchio? –

+0

Come si unisce S alla query? Potrebbe essere che poiché la chiave primaria non è in cluster, è più veloce eseguire la scansione della tabella piuttosto che saltare tra l'indice e la tabella per ogni riga. – idstam

risposta

5

Risposta breve: perché l'ottimizzatore pensa che sarebbe più veloce.

Tuttavia, proviamo a leggere la mente dell'ottimizzatore.

Dato che non è stato fornito lo schema completo della tabella, assumerò che ci sia un indice cluster su xxx.ID e che #TaxInvoiceData sia un heap. Ti aspetti un piano in cui viene rilevato l'indice PK per ogni riga in #TaxInvoiceData, ma stai selezionando xxx.Field4 che richiederà la ricerca di un segnalibro per ogni corrispondenza. Ciò potrebbe comportare 29.000 richieste di I/O casuali. Ahia.

Al contrario, SQL Server potrebbe (e apparentemente sta per) eseguire solo una quantità maggiore di I/O sequenziali più efficienti eseguendo la scansione della tabella e probabilmente sta facendo una rapida corrispondenza hash con #TaxInvoiceData.

Quindi cosa si può fare? È possibile creare un indice di copertura compreso Field4. Oppure potresti utilizzare l'indice e unire suggerimenti per forzare il piano che stai cercando (ma sospetto che le prestazioni non sarebbero buone come speri). Questa query viene utilizzata abbastanza frequentemente da fornire problemi di prestazioni delle applicazioni o semplicemente eliminando le scansioni di tabelle in linea di principio? Se quest'ultimo, si può trovare il sovraccarico di sbarazzarsi della scansione non vale la pena alla fine.


Edit:

Dal momento che hai detto che non c'è alcun indice cluster sul tavolo, anche questo può interessare quanto efficiente le ricerche dall'indice lo sono. A meno che questa tabella non visualizzi attività di inserimento estremamente pesanti, è consigliabile modificare il PK in cluster. Questo da solo potrebbe cambiare il piano, e anche se non lo facesse, è probabile che acceleri altre operazioni a causa di un sovraccarico ridotto.

+0

Grazie per la spiegazione, con cui le persone sono d'accordo. Ma perdona la mia ignoranza, non capisco perché Field4 fa la differenza poiché è la clausola select e non the dove penserei che funzionerebbe in questo modo, trova la pagina/row/leaf dalla clausola where e prendi il campo da quella riga. Quindi non sto capendo come un indice di Field4 possa migliorare una ricerca. Inoltre non esiste un indice cluster solo il PK che è stato impostato su Non-cluster per qualsiasi motivo. – Mike

+5

Se tutto ciò di cui la query ha bisogno è contenuto in un indice, SQL Server può semplicemente guardare lì ed evitare di utilizzare interamente la tabella. Questo è chiamato "indice di copertura" per la query ed è solitamente molto efficiente. Questo non è il caso per la tua situazione, perché Field4 deve essere letto dal tavolo. Il problema è dovuto al fatto che ripetutamente (molte migliaia di volte) cercare la riga nella tabella a cui fa riferimento una riga dell'indice non è molto efficiente a causa del sovraccarico I/O. L'ottimizzatore sta considerando tutto questo quando decide cosa fare. – zinglon

-2

Forse riscrivendo la query avrebbe aiutato:

SELECT X.ID, X.Field4 
FROM xxx X, #TaxInvoiceData T 
WHERE X.Id = T.Id   
AND X.Field2 = @VAR    
AND X.Field3 = 'S' 
+0

Grazie per il tempo, ma questo non ha modificato il piano di query. – Mike

+6

Questa non è la sintassi 'JOIN' standard, la riscrittura della query in questo modo non dovrebbe avere impatto * e * peggiora il codice, -1 – Matthew

Problemi correlati