web-dev-qa-db-fra.com

MySQL VARCHAR (255) UTF8 est trop long pour la clé, mais la longueur maximale est de 1000 octets

Je sais qu'il y a eu beaucoup de questions à ce sujet, mais je pense que mes calculs sont bons.

  • MySQL réserve 3 octets par caractère UTF8.
  • MyISAM autorise des clés de 1000 octets.
  • Mon UTF8 VARCHAR (255) devrait être 255 * 3 = 765 octets

À moins qu'UNQUE ne nécessite plus de 200 octets supplémentaires par entrée, pourquoi cela ne fonctionne-t-il pas?

mysql> ALTER TABLE entry ADD UNIQUE INDEX (name(255));
ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes

Y a-t-il quelque chose que je puisse faire à ce sujet?

MODIFIER:

Il s'avère que la limite est de 250. Il semble que les caractères comptent pour 4 octets pour les index uniques, mais je ne sais pas pourquoi.

MODIFIER 2:

Merci Vladislav Vaintroub, le jeu de caractères est en effet utf8mb4. Cela résout le mystère. Je n'avais vu aucune documentation sur ce changement.

Je suppose qu'il construit l'index non unique en tronquant implicitement le champ, ce qui est inacceptable pour les index uniques, donc il refuse.

Si vous saisissez à nouveau votre commentaire comme réponse, je serais heureux de l'accepter.

Solution: Spécifiez utf8, pas utf8mb4 (l'administrateur MySQL ne le permet pas, alors créez la table manuellement)

41
David Kanarek

Si vous utilisez utf8mb4 et que vous avez des index uniques sur les colonnes varchar de plus de 191 caractères, vous devrez activer innodb_large_prefix pour autoriser des colonnes plus grandes dans les index, car utf8mb4 nécessite plus d'espace de stockage que utf8 ou latin1 . Ajoutez ce qui suit à votre fichier my.cnf.

[mysqld]
innodb_file_format=barracuda
innodb_file_per_table=1
innodb_large_prefix=1
init_connect='SET collation_connection = utf8mb4_unicode_ci'
init_connect='SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

Plus d'informations sur le pourquoi et l'avenir de documentation MySQL 5.7 :

Si innodb_large_prefix est activé (la valeur par défaut dans MySQL 5.7.7), la limite de préfixe de clé d'index est de 3072 octets pour les tables InnoDB qui utilisent le format de ligne DYNAMIC ou COMPRESSED. Si innodb_large_prefix est désactivé, la limite de préfixe de clé d'index est de 767 octets pour les tables de n'importe quel format de ligne.

innodb_large_prefix est déconseillé dans MySQL 5.7.7 et sera supprimé dans une prochaine version. innodb_large_prefix a été introduit dans MySQL 5.5 pour désactiver les grands préfixes de clé d'index pour la compatibilité avec les versions antérieures d'InnoDB qui ne prennent pas en charge les grands préfixes de clé d'index.

Pour résumer, la limite n'est là que pour la compatibilité et sera augmentée dans les futures versions.

41
jsears

MySQL réserve le montant maximum pour un champ UTF8 qui est de 4 octets, c'est pourquoi vous dépassez la limite de 1000 octets. Ma recommandation est de créer le varchar à moins de 255 ou de le créer sans UTF8.

Ces deux solutions ne vous conviennent probablement pas ou vous auriez déjà essayé cela.

La seule autre solution à laquelle je peux penser est de diviser la colonne en 2 petites colonnes et de créer un index unique sur ces deux champs, mais je pense que vous obtiendriez la même erreur que ci-dessus.

Puisque vous avez probablement besoin d'UTF8, j'envisagerais sérieusement de réduire un peu la colonne varchar (255) à 250 (ou 249) pour que cela fonctionne.

7
JohnL

Quiconque a besoin d'une plus grande longueur de clé doit regarder innodb_large_prefix

visitez http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_large_prefix

7
Omesh