La déclaration de la VARCHAR
taille est-elle logique pour les performances? Y a-t-il une différence (de vitesse) entre VARCHAR(50)
et VARCHAR(255)
? Ou définir la longueur est une contrainte logique / de conception?
mysql
database-design
Sonique
la source
la source
Réponses:
Il s'agit d'une «question d'examen / entretien» très courante. Je répondrai aussi bien que possible:
Dans les formats de ligne standard pour InnoDB et MyISAM (dynamique / compact) a
VARCHAR(50)
et aVARCHAR(255)
stockeront le texte de la chaîne de la même manière - 1 octet pour la longueur et la chaîne réelle avec entre 1 et 4 octets par caractère (selon l'encodage et le caractère réel stocké).En fait, si je me souviens bien, je me souviens que quelqu'un avait modifié le dictionnaire de données avec un éditeur hexadécimal afin de changer quelque chose comme un
VARCHAR(50)
en unVARCHAR(100)
, donc cela pourrait être fait dynamiquement (normalement, cela nécessite une reconstruction de table). Et cela était possible, car les données réelles n'étaient pas affectées par ce changement.Ce n'est pas vrai avec
VARCHAR(256)
, car alors 2 octets (au moins) pour la longueur sont toujours requis.Donc, cela signifie que nous devons toujours faire
VARCHAR(255)
, ne devrions - nous? Non, il y a plusieurs raisons.Bien qu'InnoDB puisse stocker un varchar de manière dynamique, cela n'est pas vrai pour les autres moteurs. MyISAM a un format de taille de ligne fixe et les tables MEMORY sont toujours de taille fixe. Faut-il se soucier de ces autres moteurs? Oui, nous devrions le faire, car même si nous ne les utilisons pas directement, les tables MEMORY sont très couramment utilisées pour les résultats intermédiaires (tables temporaires en mémoire) , et comme les résultats ne sont pas connus au préalable, la table doit être créée avec la taille maximale possible -
VARCHAR(255)
si tel est notre type. Si vous pensez à l'espace gaspillé, si nous utilisons l''utf8' charset
encodage de MySQL , MEMORY réservera 2 octets pour la longueur + 3 * 255 octets par ligne(pour les valeurs qui ne peuvent prendre que quelques octets sur InnoDB). Cela représente presque 1 Go sur une table d'un million - uniquement pour le VARCHAR. Non seulement cela entraîne un stress mémoire inutile, mais cela peut provoquer les actions à effectuer sur le disque, ce qui peut le ralentir des milliers de fois. Tout cela en raison d'une mauvaise sélection de son type de données défini (indépendamment du contenu).Cela a également des conséquences pour InnoDB. La taille de l'index est limitée à 3072 octets et les index à colonne unique, à 767 octets *. Il est donc très probable que vous ne pourrez pas indexer entièrement un
VARCHAR(255)
champ (en supposant que vous utilisez utf8 ou tout autre encodage de longueur variable).De plus, la taille maximale des lignes en ligne pour InnoDB est d'une demi-page (environ 8000 octets) et des champs de longueur variable comme BLOB ou varchar peuvent être stockés hors page s'ils ne tiennent pas sur la demi-page . Cela a des conséquences sur les performances (parfois bonnes, parfois mauvaises, selon l'utilisation) qui ne peuvent être ignorées. Cela a provoqué une certaine bizarrerie entre les formats COMPACT et DYNAMIC. Voir, par exemple: erreur 1118: taille de ligne trop grande. utf8 innodb
Dernier point mais non le moindre, comme @ypercube me l'a rappelé, plus de 1 octet pour la longueur peut être requis même si vous utilisez
VARCHAR(255)
, car la définition est en caractères, tandis que la longueur stocke des octets. Par exemple,REPEAT('ñ', 255)
a plus de 2 ^ 255 octets dans utf8, il faudrait donc plus de 1 octet pour stocker sa longueur:Donc, le conseil général est d' utiliser le plus petit type possible , car cela peut potentiellement créer des problèmes de performances ou de gestion autrement. A
VARCHAR(100)
vaut mieux queVARCHAR(255)
(même si aVARCHAR(20)
serait mieux), même si vous ne connaissez pas la longueur exacte. Essayez d'être prudent car, à moins que le tableau ne soit trop volumineux, vous pouvez toujours modifier la définition ultérieurement.Mise à jour: En raison de la popularité explosive des chaînes de longueur variable, par exemple, avec l'utilisation des emojis, Oracle a fait pression pour améliorer les performances de ces cas. Dans les dernières versions de MySQL (5.6, 5.7), InnoDB a été défini comme moteur par défaut pour les tables temporaires intrinsèques et explicites, ce qui signifie que les champs de longueur variable sont désormais des citoyens de première classe. Cela signifie qu'il peut y avoir moins de raisons d'avoir des longueurs de caractères très limitées (mais celles-ci existent toujours).
(*) Deuxième mise à jour : large_prefix_index est désormais activé par défaut sur les dernières versions de MySQL (8.0), mais cela reste vrai pour les anciennes versions ou si vous utilisez des formats de fichiers / lignes innodb lagacy (autres que dynamiques ou compressés), mais maintenant par défaut, les index à colonne unique peuvent aller jusqu'à ces 3072 octets.
la source
Oubliez le préfixe de 1 contre 2 octets
VARCHARs
.La question sur 255 a été posée et a répondu plusieurs fois.
VARCHARs
peut conduire à l'échec deCREATE TABLE
.MEMORY
tables, avecVARCHARs
transformées enVARCHAR
. Cela signifie, par exemple, queVARCHAR(255) CHARACTER SET utf8mb4
veut une longueur fixe de 1020 octets. (Cela échouera et dégénérera en utilisant MyISAM.)Conclusion: n'utilisez pas aveuglément 255 (ou 256); faire ce qui est logique pour le schéma.
la source