Mysql
 sql >> Database >  >> RDS >> Mysql

Lunghezza dell'indice MySQL varchar

Modifica settembre 2021:uso MySQL 8.0 da un paio d'anni, quindi ecco alcune informazioni aggiornate.

Il manuale MySQL ora ha una pagina molto informativa per quanto riguarda la conversione tra utf8mb3 (attualmente noto anche come utf8 ) e utf8mb4 . utf8mb3 è deprecato e verrà rimosso infine; e quando viene rimosso, il suo alias corrente, utf8 , farà riferimento a utf8mb4 invece.

Con utf8mb3 deprecato , puoi memorizzare fino a 255 caratteri in un indice, mentre con utf8mb4 , fino a 191, quando si utilizza COMPACT o REDUNDANT formato riga.

Con COMPRESSED o DYNAMIC formato riga, i prefissi delle chiavi di indice possono essere fino a 3072 byte. Con loro, puoi indicizzare fino a 1024 caratteri per utf8mb3 e 768 caratteri per utf8mb4 .

Di seguito è riportata la mia risposta precedente, che spiega parte della logica alla base del numero di caratteri puoi indicizzare rispetto al numero di byte .

Devo rivedere la mia risposta a causa della mia ricerca. Inizialmente ho pubblicato questo (citando me stesso):

Credo che la risposta sia che non puoi sapere quanti caratteri ci saranno nell'indice perché non puoi sapere quanti byte saranno i tuoi caratteri (a meno che tu non faccia qualcosa per escludere i caratteri multi-byte).

E non ne sono sicuro, ma potrebbe comunque essere corretto, ma non nel modo in cui stavo pensando.

Ecco la risposta corretta:

MySQL presuppone 3 byte per carattere utf8. 255 caratteri è la dimensione massima dell'indice che puoi specificare per colonna, perché 256x3=768, che supera il limite di 767 byte.

Se non specifichi la dimensione dell'indice, MySQL sceglie la dimensione massima (cioè 255 per colonna). Non è possibile inserire un vincolo UNIQUE su una colonna utf8 la cui lunghezza è maggiore di 255, perché un indice univoco deve contenere l'intero valore della cella. Ma è possibile utilizzare un indice normale:indicizzerà solo i primi 255 caratteri (o i primi 767 byte?). Ed è qui che c'è ancora un po' di mistero per me.

Il mistero:posso capire perché MySQL presuppone 3 byte per carattere, per sicurezza, perché altrimenti il ​​vincolo UNIQUE potrebbe essere rotto. Ma i documenti sembrano suggerire che l'indice sia effettivamente ridimensionato in byte, non in caratteri. Supponiamo quindi di inserire 255 char (765 byte) indice su un varchar(256 ) colonna. Se i caratteri archiviati sono tutti ASCII, caratteri a 1 byte, come A-Z, a-z, 0-9, puoi inserire l'intera colonna nell'indice di 767 byte. E sembra che sia ciò che accadrebbe davvero.

Di seguito sono riportate alcune informazioni in più dalla mia risposta originale su caratteri, byte, ecc.

Secondo wikipedia , il carattere UTF-8 può essere lungo 1,2, 3 o 4 byte. Ma, secondo questa documentazione MySQL , la dimensione massima dei caratteri è 3 byte, quindi qualsiasi indice di indice di colonna superiore a 255 caratteri potrebbe raggiungere quel limite di byte. Ma a quanto ho capito, potrebbe non esserlo. Se la maggior parte dei tuoi caratteri è nell'intervallo ASCII, la dimensione media dei tuoi caratteri sarà più vicina a 1 byte. Se la dimensione media dei caratteri è, ad esempio, 1,3 byte (principalmente 1 byte, ma un numero significativo di caratteri 2-3 byte), è possibile specificare un indice di 767/1,3

Quindi, se stai memorizzando principalmente caratteri di 1 byte, il tuo limite di caratteri effettivo sarebbe più simile a:767 / 1.3 =590. Ma si scopre che non è così che funziona. 255 caratteri è il limite.

Come menzionato in questa documentazione MySQL ,

I limiti del prefisso sono misurati in byte, mentre la lunghezza del prefisso nelle istruzioni CREATE INDEX viene interpretata come numero di caratteri per tipi di dati non binari (CHAR, VARCHAR, TEXT). Tienine conto quando specifichi una lunghezza del prefisso per una colonna che utilizza un set di caratteri multibyte.

Sembra che MySQL stia consigliando alle persone di eseguire un calcolo/stima come ho appena fatto per determinare la dimensione della chiave per una colonna varchar. Ma in realtà non puoi specifica un indice maggiore di 255 per le colonne utf8.

Infine, se rimandi nuovamente al mio secondo link, c'è anche questo:

Quando l'opzione di configurazione innodb_large_prefix è abilitata, questo limite di lunghezza viene aumentato a 3072 byte, per le tabelle InnoDB che utilizzano i formati di riga DYNAMIC e COMPRESSED.

Quindi sembra che tu possa ottenere indici molto più grandi se lo desideri, con un po' di ritocco. Assicurati solo che i formati di riga siano DYNAMIC o COMPRESSED. Probabilmente puoi specificare un indice di 1023 o 1024 caratteri in questo caso.

A proposito, si scopre che puoi memorizzare caratteri a 4 byte usando [il set di caratteri utf8mb4][4]. Il set di caratteri utf8 apparentemente memorizza solo [caratteri "plane 0"][5].

MODIFICA:

Ho appena provato a creare un indice composito su una colonna varchar(511) con una colonna tinyint(1) e ho ricevuto il messaggio di errore che diceva che la dimensione massima dell'indice era 767 byte. Questo mi fa credere che MySQL presuppone che le colonne del set di caratteri utf8 contengano 3 byte per carattere (il massimo) e ti consenta di utilizzare un massimo di 255 caratteri. Ma forse è solo con indici compositi. Aggiornerò la mia risposta quando ne saprò di più. Ma per ora lascio questa modifica.