La prima cosa che devi sapere è che gli indici sono un modo per evitare di scansionare l'intera tabella per ottenere il risultato che stai cercando.
Esistono diversi tipi di indici e sono implementati nel livello di archiviazione, quindi non esiste uno standard tra di loro e dipendono anche dal motore di archiviazione che stai utilizzando.
InnoDB e l'indice B + Tree
Per InnoDB, il tipo di indice più comune è l'indice basato su albero B +, che memorizza gli elementi in un ordine ordinato. Inoltre, non è necessario accedere alla tabella reale per ottenere i valori indicizzati, il che rende la query di ritorno molto più veloce.
Il "problema" su questo tipo di indice è che è necessario richiedere il valore più a sinistra per utilizzare l'indice. Quindi, se il tuo indice ha due colonne, ad esempio last_name e first_name, l'ordine in cui richiedi questi campi è molto importante .
Quindi, data la seguente tabella:
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
Questa query trarrebbe vantaggio dall'indice:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
Ma il seguente no
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
Perché stai interrogando first_name
prima la colonna e non è la colonna più a sinistra nell'indice.
Quest'ultimo esempio è anche peggio:
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
Perché ora stai confrontando la parte più a destra del campo più a destra nell'indice.
L'indice hash
Questo è un tipo di indice diverso che purtroppo supporta solo il backend di memoria. È velocissimo ma utile solo per ricerche complete, il che significa che non è possibile utilizzarlo per operazioni come >
, <
o LIKE
.
Dal momento che funziona solo per il backend di memoria, probabilmente non lo userai molto spesso. Il caso principale che mi viene in mente in questo momento è quello in cui crei una tabella temporanea in memoria con una serie di risultati da un'altra selezione ed esegui molte altre selezioni in questa tabella temporanea utilizzando gli indici hash.
Se hai un VARCHAR
campo grande , puoi "emulare" l'uso di un indice hash quando usi un B-Tree, creando un'altra colonna e salvando un hash del valore più grande su di esso. Diciamo che stai memorizzando un url in un campo e i valori sono abbastanza grandi. È inoltre possibile creare un campo intero chiamato url_hash
e utilizzare una funzione hash simile CRC32
o qualsiasi altra funzione hash per eseguire l'hashing dell'URL durante l'inserimento. E quindi, quando è necessario eseguire una query per questo valore, è possibile fare qualcosa del genere:
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
Il problema con l'esempio sopra è che poiché la CRC32
funzione genera un hash piuttosto piccolo, si finiranno con molte collisioni nei valori con hash. Se hai bisogno di valori esatti, puoi risolvere questo problema procedendo come segue:
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
Vale comunque la pena eseguire l'hash delle cose anche se il numero di collisioni è elevato perché eseguirai solo il secondo confronto (quello della stringa) contro gli hash ripetuti.
Sfortunatamente, usando questa tecnica, devi ancora colpire la tabella per confrontare il url
campo.
Incartare
Alcuni fatti che potresti prendere in considerazione ogni volta che vuoi parlare di ottimizzazione:
Il confronto dei numeri interi è molto più veloce del confronto delle stringhe. Può essere illustrato con l'esempio sull'emulazione dell'indice hash in InnoDB
.
Forse, l'aggiunta di ulteriori passaggi in un processo rende più veloce, non più lento. Può essere illustrato dal fatto che è possibile ottimizzare a SELECT
suddividendolo in due passaggi, rendendo i primi valori di archivio in una tabella in memoria appena creata e quindi eseguendo le query più pesanti su questa seconda tabella.
MySQL ha anche altri indici, ma penso che B + Tree sia il più usato di sempre e l'hash sia una buona cosa da sapere, ma puoi trovare gli altri nella documentazione di MySQL .
Consiglio vivamente di leggere il libro "High Performance MySQL", la risposta sopra era decisamente basata sul suo capitolo sugli indici.