Risposte:
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:
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.
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
Solo per aggiungere alcune cose.
Questo è il mio approccio
Non abbiate paura di mettere > 0
o > ""
nelle vostre clausole where per le colonne non utilizzate.
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.
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.