2015-07-24 10 views
7

INDICI DI COMPRENSIONE & MANCANTI RACCOMANDAZIONI INDICEComprendere Indici e raccomandazioni indice mancante in SSMS

Sto cercando di ottenere una migliore comprensione degli indici. Ho un sacco di letture da fare e ho trovato un certo numero di risorse preziose da altri post SO, alcuni dei quali ho letto, altri ho ancora bisogno di leggere. Nel frattempo, sto cercando di ottenere prestazioni migliori dal mio database.

Ho appreso che un indice di copertura sta per essere migliore degli indici su singole colonne, quindi ho deciso di iniziare eliminando i miei singoli indici e lasciando che il piano di esecuzione della query proposto suggerisse gli indici.

SSMS INDICE RACCOMANDAZIONE

CREATE NONCLUSTERED INDEX IX_my_index_name 
ON [dbo].[my_table] ([field_a],[field_b]) 
INCLUDE (
    [field_1] 
    ,[field_2] 
    ,[field_3] 
    ,[field_4] 
    ,[field_5] 
    ,[field_6] 
) 

Tabella dei dettagli

campi 1-6 sono le colonne che usano comunemente per unire le 2 tabelle che sto usando. i campi a & b si trovano nella clausola where di alcune query che richiedono molto tempo.

Capisco di utilizzare i campi 1-6 perché per la maggior parte contengono tutti valori diversi, ma field a ha solo circa 75 valori distinti e field b ha solo 3 valori distinti. Questo è in una tabella con i record 70MM al suo interno.

Si noti che questo è un heap. Tutti i record su questa tabella provengono da un'altra tabella che ha una chiave primaria, in modo che venga fornito un valore univoco, ma non è impostato come una chiave o un indice univoco su questa tabella. SSMS non ha raccomandato di includere la colonna in questo indice. Mi chiedo come devo gestire il valore unico di questo tavolo? Un indice in cluster, unico, sto indovinando?

MIE DOMANDE

  1. voglio capire la logica dietro questa raccomandazione indice. Date le informazioni relative ai valori simili nelle colonne a & b, perché è stato consigliato?

  2. Desidero capire la differenza tra le colonne ON e le colonne INCLUDE?

risposta

2

La prima cosa che chiedo è se esiste una buona ragione per una tabella di tale dimensione non ha un indice cluster? Una chiave in cluster non deve nemmeno essere univoca (in caso contrario, SQL Server aggiungerà un "unificatore", sebbene di solito sia preferibile utilizzare una colonna IDENTITY).

per rispondere alle vostre due domande:

1) La raccomandazione indice è correlato alla query è in esecuzione. Come regola generale, le colonne suggerite corrisponderanno le colonne l'ottimizzatore di query sta usando per sondare nella tabella, quindi se avete una query come:

SELECT field1, field2, field3 
FROM table1 
WHERE field4 = 1 AND field5 = 'bob' 

L'indice suggerito è probabile che sia sul field4 e field5 colonne e in ordine di selettività (ovvero la colonna con la maggior parte delle variazioni nei valori per primi). Può includere altre colonne (ad esempio field1, field2, field3) perché in tal caso lo strumento di ottimizzazione delle query dovrà solo visitare l'indice per ottenere tali dati e non visitare la pagina dei dati.

Nota anche che a volte l'indice suggerito non è sempre quello che potresti scegliere tu stesso. Se si aggiungono più tabelle, Query Optimiser sceglierà il piano di esecuzione che ritiene più adatto ai dati, in base agli indici e alle statistiche disponibili. Potrebbe scorrere su un tavolo e sondare in un altro, quando il miglior piano possibile potrebbe farlo al contrario. Devi controllare il piano di esecuzione della query per vedere cosa sta succedendo.

Se si conosce che la query è sufficientemente selettiva da eseguire il drill-down su un piccolo intervallo di record (ad esempio una clausola where come WHERE table1.field1 = 1 AND table1.field2 = 'abc' AND table1.field3 = '2015-07-01' ...), è possibile aggiungere un indice che copra tutte le colonne di riferimento. Ciò potrebbe influire sull'ottimizzatore della query per analizzare questo indice per ottenere un numero limitato di righe da unire a un'altra tabella, piuttosto che eseguire scansioni.

Come regola generale, un buon punto di partenza quando si esaminano i piani di esecuzione sta tentando di eliminare le scansioni, in cui il server leggerà una vasta gamma di righe e fornirà indici che restringono la quantità di dati che ha essere processato.

2) Penso che gli altri hanno probabilmente spiegato questo abbastanza bene ormai - le colonne incluse sono lì in modo che quando l'indice viene letto, il server non deve quindi leggere la pagina dei dati per ottenere quei valori; sono anche memorizzati nell'indice.

La risposta iniziale che molte persone possono avere quando leggono su tali "indici di copertura" è "perché non aggiungo un intero gruppo di indici che fanno questo", o "perché non aggiungo un indice che copre tutte le colonne ".

In alcune situazioni (in genere piccole tabelle con colonne strette, come le tabelle di unione molti-a-molti), ciò è utile. Tuttavia, con ogni indice aggiunto vengono alcuni costi:

In primo luogo, ogni aggiornamento o inserimento di un valore nella tabella, l'indice deve essere aggiornato. Ciò significa che dovrai affrontare il blocco, bloccare i problemi di escalation (probabilmente deadlocking), le divisioni di pagina e la frammentazione associata. Esistono vari modi per attenuare questi problemi, ad esempio l'utilizzo di un fattore di riempimento appropriato per consentire l'inserimento di più valori in una pagina dell'indice senza doverlo dividere.

In secondo luogo, gli indici occupano spazio. Per lo meno, un indice contiene i valori chiave utilizzati e il RID (in un heap) o la chiave di clustering (in una tabella con un indice cluster). Gli indici di copertura contengono anche una copia delle colonne incluse.Se si tratta di colonne di grandi dimensioni (come grandi varchar), l'indice può essere piuttosto grande e non è inaudito per gli indici di tabelle da sommare per essere più grandi della tabella stessa. Si noti che esistono anche limiti sulla dimensione di un indice, sia in termini di colonne, sia in termini di dimensioni totali. Poiché la chiave di clustering viene sempre inclusa negli indici non in cluster su una tabella con un indice cluster (l'indice cluster si trova nella stessa pagina dati), ciò significa che una chiave cluster più piccola è migliore. Sebbene sia possibile utilizzare un indice composito, è probabile che abbia una larghezza di alcuni byte e, sebbene sia possibile utilizzare una chiave non univoca, SQL Server aggiungerà tale unificatore univoco, ovvero altri 4 byte. È consigliabile utilizzare una colonna di identificazione (int, o bigint se si prevede di avere più di 2 miliardi di righe nella tabella). Anche le identità aumentano sempre, quindi non si otterranno le suddivisioni di pagina nelle pagine di dati quando si inserisce un nuovo record, poiché andrà sempre alla fine della tabella.

quindi il tl; dr; è:

Gli indici suggeriti possono essere utili, ma spesso non forniscono l'indice migliore. se si conosce la struttura dei dati e il modo in cui verranno interrogati, è possibile creare indici contenenti le chiavi di sondaggio comunemente utilizzate.

Ordinare sempre le colonne nell'indice nell'ordine selettività (vale a dire la colonna con il maggior numero di valori per primo). Questo potrebbe sembrare contro-intuitivo, ma consente a SQL Server di trovare i dati desiderati più velocemente, con meno letture.

Le colonne incluse sono utili, ma solo di solito quando sono colonne di piccole dimensioni (ad esempio numeri interi). Se la query richiede sei colonne da una tabella e l'indice copre solo cinque di esse, SQL Server dovrà comunque visitare la pagina dati, quindi in questo caso è meglio senza le colonne incluse perché occupano solo spazio e hanno un costo di manutenzione.

+0

molto utile, grazie! – Jon

3

Le colonne ON nell'indice possono essere utilizzate per cercare le righe. Questi campi sono inclusi nell'albero dell'indice. Una volta trovate le righe, se sono necessarie colonne aggiuntive, ad esempio i campi in selezionare parti o join, devono essere recuperati dalla tabella. Questo è chiamato key lookup nel piano di esecuzione.

Se l'indice ha più colonne e non tutte le colonne sono specificate nella clausola where, le colonne possono essere utilizzate dalla prima in poi purché i campi siano assegnati. Ad esempio indice ha campi A, B, C, D e dove clausola ha campi A, B e D, quindi solo A e B può essere utilizzato per recuperare i dati.

Se la tabella ha un indice cluster, i valori delle chiavi nell'indice cluster vengono memorizzati negli altri indici e vengono utilizzati per trovare la riga dalla tabella stessa. Se non esiste alcun indice cluster, RID (ID riga) viene utilizzato in modo simile per individuare le righe dalla tabella.

Le colonne include nell'indice sono colonne aggiuntive e i relativi dati vengono archiviati a livello foglia nell'indice non in cluster. In questo modo SQL Server può leggere i dati direttamente da lì e saltare l'intera parte della lettura della tabella. Questo è chiamato covering index.

2

Un indice incluso (o indice coperto) consente a SQL Server di trovare tutte le informazioni necessarie per soddisfare la query nell'indice stesso senza dover tornare alle pagine di dati effettive per ottenere le informazioni richieste. È una copia dei dati ma le colonne nella parte inclusa non vengono utilizzate per la ricerca, ma solo per restituire i dati. Le tue tabelle dovrebbero sempre (tranne in condizioni molto, molto speciali come quando stai facendo una quantità molto grande di inserti) avere un indice cluster su di esso.

Il motivo per cui viene utilizzato un indice è la riduzione del numero di scansioni in cui SQL Server deve leggere l'intera tabella per restituire i dati. Utilizzando un indice SQL Server può cercare e leggere solo le pagine di cui ha bisogno per restituire le righe richieste. Se una colonna ha un numero limitato di valori, SQL Server può decidere di ignorare l'indice e fare una scansione. È necessario esaminare il piano di query risultante per verificare se SQL Server utilizza l'indice. Se SQL Server suggerisce un indice, in genere indica che il motore di SQL Server utilizzerà l'indice. Ma ogni indice ha un costo - deve essere mantenuto quindi non creare troppi indici.

2

Voglio capire la logica dietro questa raccomandazione indice. Date le informazioni relative ai valori simili nei campi a & b, perché è stato consigliato?

tl; dr Tutto dipende da come si stanno interrogando i dati.

Questa è una domanda difficile a cui rispondere perché dipende dalla frequenza con cui si esegue una query sulla tabella, quali tipi di query, carico del server e un sacco di altre cose.

Ad esempio, se si utilizzano i campi 1-6 in molte query eseguite con 'piani semplici', SQL Server non li considererebbe buoni canadesi per l'indicizzazione. un 'Simple Plan' o un 'Trivial Plan' è un piano che SQL SERVER fornisce a qualsiasi query che ritenga non abbastanza complicata da generare un piano completo.

Le query di lunga durata sono state "completamente esplorate" da SQL SERVER. Gli istogrammi verrebbero calcolati e archiviati. Ciò avviserà SQL SERVER che gli indici esistenti non sono sufficienti. Un piano "Completamente esplorato" è uno che SQL SERVER ha ampliato e generato un piano di query non semplice per.

Voglio capire la differenza tra le colonne ON e le colonne INCLUDE?

La differenza tra On e Incl. È.

L'istruzione includerà quella colonna nell'indice. Significa che la colonna fa parte dell'indice quando è archiviata.

Così gli indici funzionano così. L'indice di una tabella forma un B-Tree. I nodi nella B-Tree contengono il valore dell'indice di clustering e un ROWID al resto dei valori. Se si ricerca l'albero B per un valore che non fa parte dell'indice di clustering, per prima cosa troverà l'indice di clustering quindi avrà un indirizzo di memoria per il resto dei dati. Effettuerà quindi una seconda ricerca su quell'indirizzo di memoria per altri valori.

La clausola INCLUSA aggiunge i dati al livello più basso/foglia, anziché nell'albero dell'indice.Questo rende l'indice più piccolo perché non fa parte dell'albero

+0

Gli indici non hanno un indirizzo di memoria per il resto dei dati (potrebbe anche non esistere nella memoria). Presenta i valori della chiave di clustering e utilizza quelli per trovare la riga dall'indice cluster –

+0

@JamesZ. Bene, ho sostituito l'indirizzo di memoria con ROWID. La mia comprensione è ROWID è la stessa di un indirizzo di memoria. Come sono differenti? – gh9

+0

Oh sì in caso di heap è ovviamente RID, e BOL dice "identificatore di riga (RID) composto dal numero di file, numero di pagina dati e slot sulla pagina" - e presumo ci sia un qualche tipo di mappatura tra quella e indirizzo nel pool di buffer, che è la ragione per cui la ricerca RID è più veloce della ricerca della chiave. –