Mysql
 sql >> Base de données >  >> RDS >> Mysql

Longueur de l'index MySQL varchar

Édition de septembre 2021 :j'utilise MySQL 8.0 depuis quelques années maintenant, alors voici quelques informations mises à jour.

Le manuel MySQL a maintenant une page très informative concernant la conversion entre utf8mb3 (actuellement également connu sous le nom de utf8 ) et utf8mb4 . utf8mb3 est obsolète et sera supprimé finalement; et lorsqu'il est supprimé, son alias actuel, utf8 , fera référence à utf8mb4 à la place.

Avec utf8mb3 obsolète , vous pouvez stocker jusqu'à 255 caractères dans un index, tandis qu'avec utf8mb4 , jusqu'à 191, lors de l'utilisation de COMPACT ou REDUNDANT format de ligne.

Avec COMPRESSED ou DYNAMIC format de ligne, les préfixes de clé d'index peuvent aller jusqu'à 3072 octets. Avec eux, vous pouvez indexer jusqu'à 1024 caractères pour utf8mb3 , et 768 caractères pour utf8mb4 .

Vous trouverez ci-dessous ma réponse précédente, qui explique une partie de la logique derrière le nombre de caractères vous pouvez indexer par rapport au nombre d'octets .

Je dois réviser ma réponse en raison de mes recherches. J'ai initialement posté ceci (en me citant) :

Je crois que la réponse est que vous ne pouvez pas savoir combien de caractères seront dans l'index parce que vous ne pouvez pas savoir combien d'octets vos caractères seront (sauf si vous faites quelque chose pour exclure les caractères multi-octets).

Et je ne suis pas sûr, mais c'est peut-être encore correct, mais pas tout à fait comme je le pensais.

Voici la bonne réponse :

MySQL suppose 3 octets par caractère utf8. 255 caractères est la taille d'index maximale que vous pouvez spécifier par colonne, car 256x3=768, ce qui dépasse la limite de 767 octets.

Si vous ne spécifiez pas la taille de l'index, MySQL choisit la taille maximale (c'est-à-dire 255 par colonne). Une contrainte UNIQUE ne peut pas être mise sur une colonne utf8 dont la longueur est supérieure à 255, car un index unique doit contenir la valeur entière de la cellule. Mais un index normal peut être utilisé - il n'indexera que les 255 premiers caractères (ou les 767 premiers octets ?). Et c'est là qu'il y a encore du mystère pour moi.

Le MySTERY:Je peux voir pourquoi MySQL suppose 3 octets par caractère, pour des raisons de sécurité, car sinon la contrainte UNIQUE pourrait être brisée. Mais les docs semblent suggérer que l'index est en fait dimensionné en octets, pas en caractères. Donc, supposons que vous mettiez un 255 index char (765 octets) sur un varchar(256 ) colonne. Si les caractères que vous stockez sont tous des caractères ASCII à 1 octet, comme A-Z, a-z, 0-9, vous pouvez alors insérer la colonne entière dans l'index de 767 octets. Et il semble que c'est ce qui se passerait réellement.

Vous trouverez ci-dessous quelques informations supplémentaires tirées de ma réponse d'origine concernant les caractères, les octets, etc.

Selon wikipedia , le caractère UTF-8 peut avoir une longueur de 1, 2, 3 ou 4 octets. Mais, selon cette documentation mysql , la taille maximale des caractères est de 3 octets, et donc tout index d'index de colonne de plus de 255 caractères peut atteindre cette limite d'octets. Mais si je comprends bien, ce n'est peut-être pas le cas. Si la plupart de vos caractères sont dans la plage ASCII, votre taille de caractère moyenne sera plus proche de 1 octet. Si votre taille de caractère moyenne est, par exemple, de 1,3 octet (principalement 1 octet, mais un nombre important de caractères de 2 à 3 octets), vous pouvez spécifier un index de 767/1,3

Donc, si vous stockez principalement des caractères à 1 octet, votre limite réelle de caractères serait plutôt :767 / 1,3 =590. Mais il s'avère que ce n'est pas ainsi que cela fonctionne. 255 caractères est la limite.

Comme mentionné dans cette documentation MySQL ,

Les limites de préfixe sont mesurées en octets, tandis que la longueur du préfixe dans les instructions CREATE INDEX est interprétée comme un nombre de caractères pour les types de données non binaires (CHAR, VARCHAR, TEXT). Tenez-en compte lorsque vous spécifiez une longueur de préfixe pour une colonne qui utilise un jeu de caractères multi-octets.

Il semble que MySQL conseille aux gens de faire un calcul/guestimation comme je viens de le faire afin de déterminer la taille de votre clé pour une colonne varchar. Mais en fait, vous ne pouvez pas spécifiez un index supérieur à 255 pour les colonnes utf8.

Enfin, si vous vous référez à nouveau à mon deuxième lien, il y a aussi ceci :

Lorsque l'option de configuration innodb_large_prefix est activée, cette limite de longueur est portée à 3072 octets, pour les tables InnoDB qui utilisent les formats de ligne DYNAMIC et COMPRESSED.

Il semble donc que vous puissiez obtenir des index beaucoup plus grands si vous le souhaitez, avec quelques ajustements. Assurez-vous simplement que les formats de lignes sont DYNAMIC ou COMPRESSED. Vous pouvez probablement spécifier un index de 1023 ou 1024 caractères dans ce cas.

Soit dit en passant, il s'avère que vous pouvez stocker des caractères de 4 octets en utilisant [le jeu de caractères utf8mb4][4]. Le jeu de caractères utf8 ne stocke apparemment que les caractères ["plane 0"][5].

MODIFIER :

J'ai juste essayé de créer un index composite sur une colonne varchar(511) avec une colonne tinyint(1) et j'ai reçu le message d'erreur indiquant que la taille maximale de l'index était de 767 octets. Cela me fait croire que MySQL suppose que les colonnes de jeu de caractères utf8 contiendront 3 octets par caractère (le maximum) et vous permettent d'utiliser 255 caractères maximum. Mais ce n'est peut-être qu'avec des indices composites. Je mettrai à jour ma réponse au fur et à mesure que j'en saurai plus. Mais pour l'instant, je laisse cela en tant que modification.