Domanda

Recentemente ho riscontrato un indice in un database che ritengo fosse del tipo:

CREATE INDEX [IX_Foo] ON [Foo]
( Id ASC )
INCLUDE 
( SubId )

In questo caso particolare, il problema di prestazioni che stavo riscontrando (un filtro SELECT lento sia su Id che su SubId) poteva essere risolto semplicemente spostando la colonna SubId nell'indice corretto anziché come colonna inclusa.

Questo mi ha fatto pensare, tuttavia, che non capisco affatto il ragionamento dietro le colonne incluse, quando generalmente potrebbero semplicemente far parte dell'indice stesso.Anche se non mi interessa particolarmente che gli elementi siano nell'indice stesso, esiste uno svantaggio nell'avere una colonna nell'indice anziché essere semplicemente inclusa.

Dopo alcune ricerche, sono consapevole che esistono una serie di restrizioni su ciò che può essere inserito in una colonna indicizzata (larghezza massima dell'indice e alcuni tipi di colonna che non possono essere indicizzati come "immagine").In questi casi vedo che saresti costretto a includere la colonna nei dati della pagina indice.

L'unica cosa che mi viene in mente è che se ci sono aggiornamenti su SubId, non sarà necessario riposizionare la riga se la colonna è inclusa (anche se il valore nell'indice dovrebbe essere modificato).C'è qualcos'altro che mi sfugge?

Sto valutando la possibilità di esaminare gli altri indici nel database e di spostare le colonne incluse nell'indice vero e proprio, ove possibile.Sarebbe un errore?

Sono interessato principalmente a MS SQL Server, ma sono benvenute anche informazioni su altri motori DB.

È stato utile?

Soluzione

Le risposte finora sono tutte corrette, ma potrebbero non trasmettere abbastanza ciò che ottieni da un indice di copertura.

Nel tuo caso, hai un tavolo Foo e alcuni campi, incluso an Id (che presumo sia la chiave primaria) e a SubId che è un ID aggiuntivo di qualche tipo.

Hai anche un indice IX_Foo che presumo avesse solo Id dentro per ora.

Quindi ora devi trovare il file SubId per Id=4.

SELECT Id, SubId
FROM Foo
WHERE Id=4
  • SQL Server esaminerà l'istruzione SELECT e determinerà che può essere utilizzata IX_Foo
  • andrà quindi a cercare il valore Id=4 nel tuo indice IX_Foo
  • quando lo trova, ora ha bisogno del valore di SubId, pure
  • l'indice non cluster IX_Foo conterrà il valore della chiave di clustering
  • utilizzando il valore della chiave di clustering, SQL Server eseguirà una "ricerca dei segnalibri" per individuare la pagina di dati effettiva in cui si trova l'intera riga di dati
  • recupererà quella pagina ed estrarrà il valore per SubId da
  • restituirà quei valori per soddisfare la tua query

Il punto principale qui è:una volta che SQL Server ha trovato il tuo Id=4 nel IX_Foo indice, dovrà quindi eseguire un'altra operazione di I/O, una ricerca di segnalibri, per andare a recuperare l'intera riga di dati, in modo da poter trovare il SubId valore.

Se disponi di un indice di copertura, ad es. IX_Foo include anche SubId, l'I/O aggiuntivo per eseguire la ricerca dei segnalibri viene eliminato.Una volta che il valore Id=4 si trova nel IX_Foo index, la pagina dell'indice nel tuo indice non cluster includerà anche il valore di SubId - SQL Server ora può restituire i due valori richiesti nella query SELECT senza dover fare una ricerca di segnalibri extra (potenzialmente costosa e quindi lenta) solo per andare a prendere un'altra colonna Id.

Questo è il vantaggio principale della copertura degli indici: se hai bisogno solo di una o due colonne extra, oltre ai valori dell'indice su cui stai effettuando la ricerca, includendo tali valori nell'indice stesso, puoi risparmiare molte ricerche di segnalibri e quindi accelerare notevolmente le cose.Dovresti tuttavia includere solo pochissime e piccole informazioni: non duplicare intere righe di dati in tutti gli indici non cluster!Non è questo il punto.

AGGIORNAMENTO: lo scambio è questo:se hai un indice su (Id, SubId), tutte le pagine nell'indice hanno entrambe le colonne: l'intero albero dell'indice.

Se INCLUDE(SubId), i campi SubId sono presenti solo a livello foglia.

Questo significa

  • SQL Server non può cercare e confrontare su SubId (i valori non sono nell'albero dell'indice)
  • viene utilizzato meno spazio poiché i valori sono solo a livello delle foglie

Altri suggerimenti

Il motivo per avere una colonna aggiuntiva in un indice è così che quando si esegue una query che richiede solo le colonne utilizzate per l'indice è possibile soddisfare la query dall'indice di per sé. In questo modo si risparmia tempo e le risorse di tornare al tavolo. Quando questo accade, diciamo che l'indice è un che copre indice per la query.

La ragione non si potrebbe desiderare di fare questa parte colonna aggiuntiva dell ' "indice corretto" è perché quando si fanno gli inserti o aggiornamenti su quella colonna è molto più probabile avere bisogno di ri-ordinamento parti dell'indice.

Uso includere in un indice permette l'indice da utilizzare come indice di copertura (ovvero alcuni query possono essere soddisfatte con tale indice solo, senza dover eseguire una ricerca di segnalibro nell'indice cluster), senza l'aggiunta di tali colonne alla effettiva albero parte dell'indice, mantenendo così la dimensione dell'indice giù. (Le colonne inclusi sono aggiunti solo ai nodi foglia dell'indice).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top