Indicizzazione dall'inizio o quando si presentano problemi di prestazioni?


15

La mia domanda riguarda l'uso degli indici.

  1. Devo iniziare l'indicizzazione fin dall'inizio o quando si presentano problemi di prestazioni?

  2. Possiamo anche creare un indice temporaneo durante l'esecuzione di una query. Quali sono i pro e i contro di tali tecniche?

Risposte:


17

Devo iniziare l'indicizzazione fin dall'inizio o quando si presentano problemi di prestazioni?

La strategia di indicizzazione tende ad evolversi man mano che emergono modelli di utilizzo. Detto questo, ci sono anche strategie e linee guida di progettazione che possono essere applicate in anticipo.

  • Scegli una buona chiave di clustering . In genere è possibile determinare l'indice cluster appropriato in fase di progettazione, in base al modello previsto di inserti in una tabella. Se emergerà un caso convincente per un cambiamento in futuro, così sia.

  • Crea i tuoi vincoli primari e altri unici . Questi saranno applicati da indici univoci.

  • Crea le tue chiavi esterne e gli indici non cluster associati . Le chiavi esterne sono le colonne di join più frequentemente referenziate, quindi indicizzale dall'inizio.

  • Crea indici per qualsiasi domanda ovviamente altamente selettiva . Per i pattern di query che già conosci saranno altamente selettivi e probabilmente utilizzeranno le ricerche anziché le scansioni.

Oltre a quanto sopra, adottare un approccio graduale e olistico all'implementazione di nuovi indici. Per olistica, intendo valutare il potenziale beneficio e l'impatto su tutte le query e gli indici esistenti quando si valuta un'aggiunta.

Un problema non raro nei circoli di SQL Server è la sovraespressione, a seguito della guida dei DMV dell'indice mancanti e dei suggerimenti SSMS. Nessuno di questi strumenti valuta gli indici esistenti e suggerisce allegramente di creare un nuovo indice di 6 colonne anziché aggiungere una singola colonna a un indice di 5 colonne esistente.

-- If you have this
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
)

-- But your query would benefit from the addition of a column
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

-- SSMS will suggest you create this instead
CREATE NONCLUSTERED INDEX [IX_MyTable_AnotherIndexWithTheSameColumnsAsTheExistingIndexPlusCol6] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

Kimberly Tripp ha del materiale eccellente sulla strategia di indicizzazione che mentre SQL focalizzato è applicabile ad altre piattaforme. Per la gente di SQL Server, ci sono alcuni strumenti utili per identificare i duplicati come nell'esempio sopra.

Possiamo anche creare un indice temporaneo durante l'esecuzione di una query. Quali sono i pro e i contro di tali tecniche?

Questo di solito si applica solo a query eseguite raramente, in genere ETL. Devi valutare:

  1. Il tempo impiegato per creare l'indice riduce il tempo di esecuzione della query.
  2. L'overhead di manutenzione di lasciare l'indice in posizione supera il tempo impiegato per creare / eliminare quando è necessario.

3
+1 Chiave cluster, Chiave esterna, Chiave unica / primaria e non fidarsi dei DMV indice mancanti al valore nominale ... Tutte queste cose sono un ottimo consiglio. Gestire gli indici esistenti, in SQL Server, è abbastanza facile da monitorare usando il DMV sys.dm_db_index_usage_stats. Per un periodo di tempo, è possibile elencare gli indici che non sono stati scansionati o ricercati, pur vedendo che questi stessi indici sono stati aggiornati più volte. Questo è indicativo di sovrastima.
Matt M

1
+1, tuttavia "crea indici per qualsiasi query ovviamente altamente selettiva". non copre tutti gli altri scenari. Gli indici possono aiutare a ordinare i risultati anche se le tue query non sono altamente selettive. Possono anche velocizzare le query se coprono tutte le colonne selezionate.
Unreason,

1
D'accordo, ma la domanda era cercare un punto di partenza piuttosto che la fine del gioco. Identificare le query da coprire è difficile senza schemi di utilizzo poiché raramente è possibile coprirle tutte.
Mark Storey-Smith,

8

Esistono davvero dei rischi associati a entrambi gli approcci:

Opzione a) Indice dall'inizio, ma non rendersi conto di aver creato un numero di indici che non vengono mai utilizzati. Questi aggiungono un certo sovraccarico (in particolare alle query che modificano i dati, ma anche con l'ottimizzazione delle istruzioni SELECT che cercano di identificare il miglior indice).

Dovrai disciplinarti per identificare gli indici non più utilizzati e provare a rimuoverli (PostgreSQL può farlo; sfortunatamente MySQL in confronto è molto debole in questo caso.)

Opzione b) Non aggiungere indici finché le persone non iniziano a lamentarsi o gli strumenti diagnostici attivano che determinate query sono lente e potrebbero essere migliorate.

Il rischio che si presenta è che non si abbia una finestra temporale abbastanza grande tra quando si nota che è necessario l'indice e quando è necessario aggiungerlo.

PostgreSQL supporta la creazione di indici CONCURRENTLY, il che riduce parte dello stress derivante da questo requisito di aggiunta improvvisa dell'indice, ma ci sono alcuni avvertimenti annotati nel manuale.


L'opzione (b) tende ad essere la mia preferenza, ma penso che un ibrido di entrambe le opzioni sia probabilmente la soluzione migliore. Ha a che fare con il tuo livello di confidenza se pensi che verrà effettivamente utilizzato un indice.

Ciò che rende questa discussione particolarmente complessa è che di solito è facile cambiare gli indici, ma è più difficile cambiare lo schema. Non voglio promuovere la reazione ritardata di b come scusa per essere sconsiderati.


4

Oltre alla risposta di Mark

Puoi avere un'idea disponendo di dati di test realistici alle quantità previste. Ho visto molti, troppi (troppi) casi in cui una query funziona correttamente con 1000 righe ma non il milione in produzione.

Se puoi, lavora su una copia della produzione in seguito,

Certo, ho visto lo strano problema solo in produzione a causa dei modelli di utilizzo quando tutto il resto è identico

Indici temporanei? Al di fuori dei modelli di carico ETL, se ne hai bisogno una volta ti serviranno di nuovo. Non dimenticare: un indice di creazione / eliminazione è una scrittura ed è registrato = più carico


3

Solo per aggiungere alcune cose.

  • Gli indici temporanei sono un'idea terribile ... a meno che l'indice non si trovi su una tabella temporanea.
  • Gli indici occupano molto più spazio dati (oltre ad altre spese generali) di quanto le persone realizzino. Pertanto, crearli in modo conservativo.

Questo è il mio approccio

  1. Simile a Mark, crea indici in cui hanno senso, ma non in ritardo.
  2. Non è necessario attendere che le prestazioni siano lente per creare nuovi indici. Ogni volta che scrivi un nuovo SQL, esegui un piano di query (preferibilmente sul tuo database di prod). Dovresti essere in grado di vedere se è necessario un nuovo indice.
  3. Non abbiate paura di mettere > 0o > ""nelle vostre clausole where per le colonne non utilizzate.

    1. Vale a dire, supponiamo che tu abbia un indice su A, B, C e D. Tuttavia, hai solo informazioni A, B, D. Non c'è motivo per cui non puoi farlo-
    select * from blah 
    where A="one" 
    and B="two" 
    and C>=""     --to match index
    and D="four"
    
    --This will use your existing index. No need to create a redundant one.

Un'altra cosa, questo è nel forum "dba", ma la creazione di indici dovrebbe essere davvero la responsabilità dello sviluppatore, non quella del dba. (Per i casi in cui sono completamente separati.)
user606723

2
L'affermazione relativa allo spazio occupato dagli indici è un po 'fuorviante, in un indice non cluster ci sono pochissime spese generali. Se potessi pubblicare una domanda su questo punto varrebbe la pena esplorare ulteriormente. In secondo luogo, non sono d'accordo sul fatto che la creazione dell'indice sia il dominio dello sviluppatore. È una delle aree in cui la collaborazione tra sviluppatore e DBA può produrre i migliori risultati.
Mark Storey-Smith,

1
Ti darò un esempio di uno dei nostri tavoli. dimensione tabella: 21052404 KB. Dimensione di un indice non cluster in questa tabella: 6637470 KB. Molto poco sopra la testa? Penso di no. Inoltre, non sto dicendo che i DBA non dovrebbero essere collaborati, sto dicendo che dovrebbe essere responsabilità dello sviluppatore determinare se è necessario creare un nuovo indice. Non dovrebbero scrivere SQL e aspettarsi che il dbas lo capisca da solo.
user606723,

1
Non puoi citare numeri del genere senza contesto. Senza specificare le colonne dell'indice NC e la chiave cluster, è impossibile calcolare la percentuale di overhead rispetto ai dati.
Mark Storey-Smith,

Touche. La chiave è un [numerico (24), carattere, data] e le colonne NC sono [data, numero (24)]. (Solo due colonne in questo particolare indice).
user606723,

2

Proverò a rispondere solo alla prima domanda. Se riesci a stimare anche approssimativamente dall'inizio quanti record avrai nelle tue tabelle dopo un certo periodo di tempo, allora direi che è meglio iniziare dall'inizio per progettare alcuni indici. Prova a utilizzare alcuni strumenti di test o script di test che automatizzeranno il maggior numero possibile di chiamate per le chiamate dell'applicazione che ritieni verranno utilizzate più spesso e vedrai quali scansioni di tabelle possono essere evitate dall'inizio.

All'inizio sarà un'ipotesi, ma col tempo, dato che hai le statistiche di utilizzo adeguate, avrai un'immagine più chiara.

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.