Indici non cluster: chiavi e non chiavi


8

Voglio solo assicurarmi di essere sulla strada giusta con questi concetti, quindi qualsiasi feedback sarebbe molto apprezzato.

Ecco la mia teoria della query che ho appena ottimizzato, attraverso un processo di tentativi ed errori e leggendo la documentazione MSDN.

The Query

DECLARE @pic_id int
SET pic_id = 1

SELECT ROW_NUMBER() OVER (ORDER BY pic_date desc) AS row_num, *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND (hidden = 0 OR pic_id = @pic_id)

L'indice

CREATE NONCLUSTERED INDEX [IX_tbl_pics] ON [dbo].[tbl_pics] 
(
    [map_id] ASC,
    [deleted] ASC,
    [pic_date] DESC
)
INCLUDE ( [hidden], [pic_id] )

C'è anche un indice PK su pic_id

La teoria

Le colonne chiave sono così, perché vengono utilizzate in una clausola WHERE (ma non utilizzate in una situazione OR) o ORDER BY.

Le colonne non chiave (INCLUDE) in quanto tali, perché vengono utilizzate in WHERE, ma poiché sono utilizzate in uno scenario OR non possono (non possono = non migliorare le prestazioni) essere una colonna chiave.

Queste presunzioni sono corrette? In caso contrario, cosa mi sto perdendo?

Grazie!

Risposte:


8

Stai chiedendo a Query Optimizer di produrre un piano in grado di rispondere alla query:

SELECT *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND hidden = 0;

Il resto è lanugine (incluso il OR pic_id = @pic_id). Questa sarà una scansione della tabella, garantita, a causa della bassa selettività dei predicati coinvolti (ne sono sicuro deletede hiddensono 0/1, e map_ipdubito che abbia un impatto significativo). L'unico predicato che potrebbe salvare la query è pic_id = @pic_idma ponendolo in una condizione OR hai ucciso è una possibilità. Nessun indice secondario può aiutarlo, realisticamente. L'aggiunta di ROW_NUMBER pubblicherà una specie, molto probabilmente, ma il vero danno è la scansione.

Questa è una causa persa. Vieni con requisiti realistici.


6

La chiave primaria è anche l'indice cluster? In tal caso, non vi è alcun motivo INCLUDE (pic_id)perché l'indice cluster univoco verrà già utilizzato come segnalibro nell'indice non cluster.

Per quanto riguarda ciò di cui stai parlando con l'OR, questa è effettivamente una seconda parte di WHERE, ma stai solo facendo affidamento sulla selettività della prima per fare la maggior parte del lavoro (facendo affidamento su INCLUDE per evitare di andare a la tavola).

Ma avendo * dentro, potresti dover andare al tavolo comunque.

D'altra parte, potrei non progettare i miei indici in base a una singola query, a meno che questa query non sia utilizzata in modo molto pesante senza tenere conto di più del carico. E ancora dare un'occhiata al piano di esecuzione non poteva far male.

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.