La tabella Retailer_Relations ha il seguente indice PK composito e l'indice suggerito-
Sebbene gli indici mancanti possano essere utili e sicuramente funzionanti, non spenderei troppo tempo sugli indici mancanti, questi suggerimenti vengono creati sul piano di esecuzione stimato, non sul piano di esecuzione effettivo.
Più precisamente, questi suggerimenti sull'indice si basano sul presupposto di ridurre il costo di Query Bucks ™ utilizzato dagli operatori del piano. L'ottimizzatore calcola i costi stimati e aggiunge di conseguenza suggerimenti sull'indice mancanti.
Di conseguenza potrebbero essere molto sbagliati. Se non sei sicuro che possa essere d'aiuto, la cosa migliore da fare è testare la situazione prima e dopo. È possibile farlo aggiungendo l'istruzione
SET STATISTICS IO, TIME ON;
prima di eseguire la query.
Inoltre, è possibile utilizzare statisticsparser per semplificare la lettura di queste statistiche.
Questo potrebbe essere dovuto all'ordine delle colonne nell'indice?
Ciò è corretto, la creazione dell'indice mancante può migliorare la selettività sulle query, ad esempio se la query è simile alla seguente:
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
o in questo modo:
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
Il ragionamento alla base di ciò è che entrambi gli indici potrebbero cercare su RetailerID, quella parte non cambierà. Ma cosa succede se vengono applicati filtri / ordini aggiuntivi su RelationType? Sarebbe ovunque nell'indice cluster, come risultato del fatto che è il terzo valore chiave, non il secondo valore chiave. E come sappiamo, è il secondo valore chiave nell'NCI.
Va bene, ma quando o come l'indice non cluster migliorerebbe la query?
Un paio di casi potrebbero essere:
- Se relationshipType filtra molti valori, l'I / O residuo potrebbe essere elevato, con conseguente possibile necessità dell'indice non cluster (Query # 1)
- L'ordinamento su due colonne avviene (solo andata) e il gruppo di risultati è grande (query n. 2).
- Come accennato da @AaronBertrand: se la differenza di dimensioni dell'elemento della configurazione rispetto all'NCI è considerevole, l'aggiunta dell'NCI ridurrà le pagine lette dalle query che ne beneficiano.
Nota laterale NCI
Come nota a margine, l'aggiunta delle colonne chiave all'elenco di inclusione nel tuo NCI non è esattamente necessaria, poiché le colonne chiave CI sono automaticamente incluse in tutti gli indici non cluster.
Puoi scegliere di farlo se non sei sicuro che l'indice cluster rimarrà lo stesso e desideri che la colonna sia sempre inclusa.
Per quanto riguarda la query stessa, se hai aggiunto il piano di esecuzione tramite PasteThePlan , potremmo fornire ulteriori informazioni sull'indicizzazione / miglioramento della query.
analisi
Crea una tabella e aggiungi alcune righe
CREATE TABLE Retailer_Relations (
RetailerID int ,
RelatedRetailerID int ,
RelationType smallint,
CreatedOn datetime,
CONSTRAINT PK_Retailer_Relations
PRIMARY KEY CLUSTERED (
RetailerID ASC,
RelatedRetailerID ASC,
RelationType ASC
) ON [PRIMARY])
DECLARE @I Int = 1
WHILE @I < 1000
BEGIN
INSERT INTO Retailer_Relations(RetailerID,RelatedRetailerID,RelationType,CreatedOn)
VALUES(@I,@I,@I,GETDATE()
)
set @I += 1
END
Query n. 1
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
Pianificare senza indice Qui
Mentre sta effettuando una ricerca, sta effettuando una ricerca su RetailerID. Successivamente emette un predicato I / O residuo su RelationType
Aggiungi l'indice
CREATE NONCLUSTERED INDEX IX_TEST
ON Retailer_Relations (
RetailerID,
RelationType
)
INCLUDE (
RelatedRetailerID
)
Il predicato residuo è sparito, tutto accade in un predicato di ricerca, su entrambe le colonne.
Progetto esecutivo
Con la seconda query, la disponibilità dell'indice aggiunto diventa ancora più ovvia:
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
Pianificare senza l'indice, con un operatore di ordinamento:
Pianificare con l'indice, l'utilizzo dell'indice rimuove l'operatore di ordinamento