MySQL esclude dal finanziamento indicizzazione un valore pieno di BLOB
, TEXT
e lunghe VARCHAR
colonne in quanto i dati in essi contenuti può essere enorme, e implicitamente indice DB sarà grande, ciò significa che nessun beneficio dall'indice.
MySQL richiede che tu definisca i primi N caratteri da indicizzare, e il trucco è scegliere un numero N che sia abbastanza lungo da dare una buona selettività, ma abbastanza corto da risparmiare spazio. Il prefisso dovrebbe essere abbastanza lungo da rendere l'indice quasi utile quanto lo sarebbe se indicizzassi l'intera colonna.
Prima di andare oltre, definiamo alcuni termini importanti. La selettività dell'indice è il rapporto tra i valori indicizzati distinti totali e il numero totale di righe . Ecco un esempio per la tabella di test:
+-----+-----------+
| id | value |
+-----+-----------+
| 1 | abc |
| 2 | abd |
| 3 | adg |
+-----+-----------+
Se indicizziamo solo il primo carattere (N = 1), la tabella dell'indice sarà simile alla seguente tabella:
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| a | 1,2,3 |
+---------------+-----------+
In questo caso, la selettività dell'indice è uguale a IS = 1/3 = 0,33.
Vediamo ora cosa accadrà se aumentiamo il numero di caratteri indicizzati a due (N = 2).
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| ab | 1,2 |
| ad | 3 |
+---------------+-----------+
In questo scenario IS = 2/3 = 0,66 significa che abbiamo aumentato la selettività dell'indice, ma abbiamo anche aumentato la dimensione dell'indice. Il trucco è trovare il numero minimo N che porterà alla massima selettività dell'indice .
Esistono due approcci che è possibile eseguire calcoli per la tabella del database. Farò dimostrazione su questo dump del database .
Supponiamo di voler aggiungere all'indice la colonna last_name negli impiegati della tabella e vogliamo definire il numero N più piccolo che produrrà la migliore selettività dell'indice.
Innanzitutto cerchiamo di identificare i cognomi più frequenti:
select count(*) as cnt, last_name
from employees
group by employees.last_name
order by cnt
+-----+-------------+
| cnt | last_name |
+-----+-------------+
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Farris |
| 222 | Sudbeck |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Neiman |
| 218 | Mandell |
| 218 | Masada |
| 217 | Boudaillier |
| 217 | Wendorf |
| 216 | Pettis |
| 216 | Solares |
| 216 | Mahnke |
+-----+-------------+
15 rows in set (0.64 sec)
Come puoi vedere, il cognome Baba è il più frequente. Ora troveremo i prefissi last_name che si verificano più frequentemente , iniziando con i prefissi a cinque lettere.
+-----+--------+
| cnt | prefix |
+-----+--------+
| 794 | Schaa |
| 758 | Mande |
| 711 | Schwa |
| 562 | Angel |
| 561 | Gecse |
| 555 | Delgr |
| 550 | Berna |
| 547 | Peter |
| 543 | Cappe |
| 539 | Stran |
| 534 | Canna |
| 485 | Georg |
| 417 | Neima |
| 398 | Petti |
| 398 | Duclo |
+-----+--------+
15 rows in set (0.55 sec)
Ci sono molte più occorrenze di ogni prefisso, il che significa che dobbiamo aumentare il numero N fino a quando i valori sono quasi gli stessi dell'esempio precedente.
Ecco i risultati per N = 9
select count(*) as cnt, left(last_name,9) as prefix
from employees
group by prefix
order by cnt desc
limit 0,15;
+-----+-----------+
| cnt | prefix |
+-----+-----------+
| 336 | Schwartzb |
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Sudbeck |
| 222 | Farris |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Mandell |
| 218 | Neiman |
| 218 | Masada |
| 217 | Wendorf |
| 217 | Boudailli |
| 216 | Cummings |
| 216 | Pettis |
+-----+-----------+
Ecco i risultati per N = 10.
+-----+------------+
| cnt | prefix |
+-----+------------+
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Sudbeck |
| 222 | Farris |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Mandell |
| 218 | Neiman |
| 218 | Masada |
| 217 | Wendorf |
| 217 | Boudaillie |
| 216 | Cummings |
| 216 | Pettis |
| 216 | Solares |
+-----+------------+
15 rows in set (0.56 sec)
Questi sono ottimi risultati. Ciò significa che possiamo creare un indice su colonna last_name
indicizzando solo i primi 10 caratteri. Nella tabella definizione colonna last_name
è definito come VARCHAR(16)
, e questo significa che abbiamo salvato 6 byte (o più se ci sono caratteri UTF8 nel cognome) per voce. In questa tabella ci sono 1637 valori distinti moltiplicati per 6 byte è di circa 9 KB e immagina come questo numero aumenterebbe se la nostra tabella contiene milioni di righe.
Puoi leggere altri modi per calcolare il numero di N nel mio post Indici prefissati in MySQL .
UNIQUE
chiavi?