Quali colonne fanno generalmente buoni indici?


98

In seguito a " Cosa sono gli indici e come posso utilizzarli per ottimizzare le query nel mio database? ", Dove sto cercando di ottenere informazioni sugli indici, quali colonne sono buoni candidati per l'indice? Specificamente per un database MS SQL?

Dopo un po 'di ricerca su Google, tutto ciò che ho letto suggerisce che le colonne che sono generalmente in aumento e uniche fanno un buon indice (cose come auto_increment di MySQL), lo capisco, ma sto usando MS SQL e sto usando GUID per chiavi primarie, quindi sembra che gli indici non gioverebbero alle colonne GUID ...


Che ne dici di un "libro di cucina": mysql.rjweb.org/doc.php/index_cookbook_mysql
Rick James,

Risposte:


110

Gli indici possono svolgere un ruolo importante nell'ottimizzazione delle query e nella ricerca rapida dei risultati nelle tabelle. Quindi è il passaggio più importante selezionare le colonne da indicizzare. Ci sono due punti principali in cui possiamo considerare l'indicizzazione: colonne a cui si fa riferimento nella clausola WHERE e colonne utilizzate nelle clausole JOIN. In breve, tali colonne dovrebbero essere indicizzate rispetto alle quali è necessario cercare particolari record. Supponiamo di avere una tabella denominata acquirenti in cui la query SELECT utilizza indici come di seguito:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

Poiché "buyer_id" è referenziato nella parte SELECT, MySQL non lo userà per limitare le righe scelte. Quindi, non è necessario indicizzarlo. Il seguente è un altro esempio leggermente diverso da quello sopra:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

In base alle query precedenti first_name, le colonne last_name possono essere indicizzate poiché si trovano nella clausola WHERE. Anche un campo aggiuntivo, country_id dalla tabella country, può essere considerato per l'indicizzazione perché si trova in una clausola JOIN. Quindi l'indicizzazione può essere considerata su ogni campo nella clausola WHERE o in una clausola JOIN.

Il seguente elenco offre anche alcuni suggerimenti che dovresti sempre tenere a mente quando intendi creare indici nelle tue tabelle:

  • Indicizza solo le colonne richieste nelle clausole WHERE e ORDER BY. L'indicizzazione delle colonne in abbondanza comporterà alcuni svantaggi.
  • Prova a trarre vantaggio dalla funzionalità "prefisso indice" o "indice a più colonne" di MySQL. Se crei un indice come INDEX (first_name, last_name), non creare INDEX (first_name). Tuttavia, "prefisso indice" o "indice a più colonne" non è consigliato in tutti i casi di ricerca.
  • Utilizzare l'attributo NOT NULL per quelle colonne in cui si considera l'indicizzazione, in modo che i valori NULL non vengano mai memorizzati.
  • Utilizza l'opzione --log-long-format per registrare le query che non utilizzano gli indici. In questo modo, puoi esaminare questo file di registro e modificare le tue query di conseguenza.
  • L'istruzione EXPLAIN ti aiuta a rivelare il modo in cui MySQL eseguirà una query. Mostra come e in quale ordine le tabelle vengono unite. Questo può essere molto utile per determinare come scrivere query ottimizzate e se le colonne devono essere indicizzate.

Aggiornamento (23 febbraio 15):

Qualsiasi indice (buono / cattivo) aumenta il tempo di inserimento e aggiornamento.

A seconda dei tuoi indici (numero di indici e tipo), il risultato viene cercato. Se il tempo di ricerca aumenterà a causa dell'indice, allora non sarà indice.

Probabilmente in qualsiasi libro, "Pagina indice" potrebbe avere la pagina iniziale del capitolo, l'inizio del numero della pagina dell'argomento e anche l'inizio della pagina dell'argomento secondario. Alcuni chiarimenti nella pagina Indice aiutano, ma un indice più dettagliato potrebbe confonderti o spaventarti. Anche gli indici hanno memoria.

La selezione dell'indice dovrebbe essere saggia. Tieni presente che non tutte le colonne richiederebbero index.


Grazie Somnath, quindi implica che gli indici dovrebbero essere creati solo per le colonne in cui intendiamo utilizzare WHERE, JOINSoppure HAVING?
Muhammad Babar

3
Sì, utilizza gli indici per le colonne in cui prevedi di utilizzare WHERE, JOINS o HAVING. Ma tieni anche presente che tutte le colonne delle condizioni non richiedono indici. A volte in cui la colonna della condizione viene utilizzata solo una volta, quindi potrebbe non richiedere l'indice mentre un'altra colonna della condizione viene utilizzata in molte query, quindi preferisci di più per l'indicizzazione a quella colonna.
Somnath Muluk

1
La risposta trarrebbe vantaggio dall'inserimento di "colonne a cui si fa riferimento nella clausola WHERE e colonne utilizzate nelle clausole JOIN" in una sezione TL; DR.
jpmc26

Quindi stai dicendo che se nella mia WHEREclausola sto controllando il valore di un campo in cui la sua colonna può assumere solo due valori, allora dovrei indicizzare quella colonna binaria? Sembra sbagliato.
AjaxLeung

@AjaxLeung: Ricorda la massima di Knuth "L'ottimizzazione prematura è la radice di tutti i mali". Puoi creare un indice su colonne binarie, ma dovrebbe dipendere da quale costo (come i tempi di inserimento, aggiornamento). Se la logica aziendale dipende spesso da tale switch binario, potrebbe essere necessario che la colonna binaria abbia index.
Somnath Muluk

20

Alcune persone hanno risposto a una domanda simile qui: come fai a sapere cos'è un buon indice?

Fondamentalmente, dipende davvero da come interrogherai i tuoi dati. Desideri un indice che identifichi rapidamente un piccolo sottoinsieme del tuo set di dati che è rilevante per una query. Se non esegui mai query per datestamp, non hai bisogno di un indice su di esso, anche se è per lo più unico. Se tutto ciò che fai è ottenere eventi accaduti in un determinato intervallo di date, ne vuoi sicuramente uno. Nella maggior parte dei casi, un indice di genere è inutile, ma se tutto ciò che fai è ottenere statistiche su tutti i maschi e separatamente, su tutte le femmine, potrebbe valere la pena crearne uno. Scopri quali saranno i tuoi modelli di query e l'accesso a quale parametro restringe maggiormente lo spazio di ricerca, e questo è il tuo indice migliore.

Considera anche il tipo di indice che crei: gli alberi B sono buoni per la maggior parte delle cose e consentono query di intervallo, ma gli indici hash ti portano dritto al punto (ma non consentono intervalli). Altri tipi di indici hanno altri vantaggi e svantaggi.

In bocca al lupo!


9

Tutto dipende dalle domande che ti aspetti di chiedere sulle tabelle. Se chiedi tutte le righe con un certo valore per la colonna X, dovrai eseguire una scansione completa della tabella se non è possibile utilizzare un indice.

Gli indici saranno utili se:

  • La colonna o le colonne hanno un alto grado di unicità
  • Spesso è necessario cercare un determinato valore o intervallo di valori per la colonna.

Non saranno utili se:

  • Stai selezionando una grande percentuale (> 10-20%) delle righe nella tabella
  • L'utilizzo di spazio aggiuntivo è un problema
  • Si desidera massimizzare le prestazioni dell'inserto. Ogni indice su una tabella riduce le prestazioni di inserimento e aggiornamento perché devono essere aggiornati ogni volta che i dati cambiano.

Le colonne della chiave primaria sono in genere ottime per l'indicizzazione perché sono univoche e vengono spesso utilizzate per cercare le righe.


le ricerche di stringhe in cui il valore può essere ovunque all'interno della stringa potrebbero far sì che non utilizzi quegli indici in quel caso.
Arthur Thomas,

5

In generale (non uso mssql, quindi non posso commentare in modo specifico), le chiavi primarie fanno buoni indici. Sono univoci e devono avere un valore specificato. (Inoltre, le chiavi primarie creano indici così buoni che normalmente hanno un indice creato automaticamente.)

Un indice è effettivamente una copia della colonna che è stata ordinata per consentire la ricerca binaria (che è molto più veloce della ricerca lineare). I sistemi di database possono utilizzare vari trucchi per velocizzare ulteriormente la ricerca, in particolare se i dati sono più complessi di un semplice numero.

Il mio suggerimento sarebbe di non utilizzare inizialmente alcun indice e di profilare le tue query. Se una query particolare (come la ricerca di persone per cognome, ad esempio) viene eseguita molto spesso, prova a creare di nuovo un indice sugli attributi e sul profilo pertinenti. Se si riscontra una notevole accelerazione delle query e un trascurabile rallentamento degli inserimenti e degli aggiornamenti, mantenere l'indice.

(Mi scuso se ripeto cose menzionate nell'altra tua domanda, non le avevo mai viste prima.)


5

Qualsiasi colonna che verrà utilizzata regolarmente per estrarre i dati dalla tabella dovrebbe essere indicizzata.

Questo include: chiavi esterne -

select * from tblOrder where status_id=:v_outstanding

campi descrittivi -

select * from tblCust where Surname like "O'Brian%"

Le colonne non devono essere univoche. In effetti, puoi ottenere prestazioni davvero buone da un indice binario durante la ricerca di eccezioni.

select * from tblOrder where paidYN='N'

La tua esplicita menzione delle chiavi esterne mi ha davvero chiarito le cose considerando i join.
pfabri

3

Dipende davvero dalle tue domande. Ad esempio, se scrivi quasi solo su una tabella, è meglio non avere indici, rallentano solo le scritture e non vengono mai utilizzati. Qualsiasi colonna che utilizzi per unirti a un'altra tabella è un buon candidato per un indice.

Inoltre, leggi la funzionalità degli indici mancanti. Monitora le query effettive utilizzate sul database e può dirti quali indici avrebbero migliorato le prestazioni.


3

Una colonna GUID non è il miglior candidato per l'indicizzazione. Gli indici sono più adatti alle colonne con un tipo di dati a cui può essere assegnato un ordine significativo, cioè ordinati (numero intero, data, ecc.).

Non importa se i dati in una colonna sono generalmente in aumento. Se crei un indice sulla colonna, l'indice creerà la propria struttura di dati che farà semplicemente riferimento agli elementi effettivi nella tabella senza preoccuparsi per l'ordine memorizzato (un indice non cluster). Quindi, ad esempio, è possibile eseguire una ricerca binaria sulla struttura dei dati dell'indice per fornire un recupero rapido.

È anche possibile creare un "indice cluster" che riordinerà fisicamente i dati. Tuttavia puoi avere solo uno di questi per tabella, mentre puoi avere più indici non cluster.


Bene, non è del tutto accurato in questo modo. Puoi facilmente creare un indice regolare, non cluster su una colonna GUID, perché no? Il GUID ha un grosso svantaggio se lo usi come chiave di clustering (ad esempio per l'INDICE CLUSTERATO), quindi è un disastro da usare.
marc_s

1

La vecchia regola pratica erano le colonne che vengono utilizzate molto nelle clausole WHERE, ORDER BY e GROUP BY, o qualsiasi altra che sembra essere usata frequentemente nei join. Tieni presente che mi riferisco agli indici, NON alla chiave primaria

Non per dare una risposta "vanigliata", ma dipende davvero da come si accede ai dati


1

La tua chiave primaria dovrebbe sempre essere un indice. (Sarei sorpreso se non fosse indicizzato automaticamente da MS SQL, in effetti.) Dovresti anche indicizzare le colonne tu SELECTo ORDERfrequentemente; il loro scopo è sia la ricerca rapida di un singolo valore che l'ordinamento più veloce.

L'unico vero pericolo nell'indicizzazione di toomolte colonne è il rallentamento delle modifiche alle righe in tabelle di grandi dimensioni, poiché anche gli indici devono essere aggiornati. Se non sei davvero sicuro di cosa indicizzare, calcola solo il tempo delle query più lente, guarda quali colonne vengono utilizzate più spesso e indicizzale. Quindi guarda quanto sono più veloci.


1

I tipi di dati numerici ordinati in ordine crescente o decrescente sono buoni indici per molteplici ragioni. Innanzitutto, i numeri sono generalmente più veloci da valutare rispetto alle stringhe (varchar, char, nvarchar, ecc.). In secondo luogo, se i valori non sono ordinati, potrebbe essere necessario mescolare righe e / o pagine per aggiornare l'indice. Questo è un sovraccarico aggiuntivo.

Se utilizzi SQL Server 2005 e imposti l'uso di identificatori univoci (guids) e NON è necessario che siano di natura casuale, controlla il tipo di identificatore univoco sequenziale.

Infine, se stai parlando di indici cluster, stai parlando del tipo di dati fisici. Se hai una stringa come indice cluster, potrebbe diventare brutto.


0

Dovrebbe essere ancora più veloce se stai usando un GUID. Supponi di avere i record

  1. 100
  2. 200
  3. 3000
  4. ....

Se hai un indice (ricerca binaria, puoi trovare la posizione fisica del record che stai cercando in tempo O (lg n), invece di cercare in sequenza O (n) tempo. Questo perché non sai quali record hai nella tua tavola.


0

L'indice migliore dipende dal contenuto della tabella e da ciò che stai cercando di ottenere.

Ad esempio, un database dei membri con una chiave primaria del numero di previdenza sociale dei membri. Scegliamo la SS perché l'applicazione priamry si riferisce all'individuo in questo modo, ma si desidera anche creare una funzione di ricerca che utilizzi il nome e il cognome dei membri. Suggerirei quindi di creare un indice su questi due campi.

Dovresti prima scoprire quali dati interrogherai e poi determinare quali dati devi indicizzare.

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.