Importance de la longueur varchar dans la table MySQL

112

J'ai une table MySQL où les lignes sont insérées dynamiquement. Parce que je ne peux pas être certain de la longueur des cordes et que je ne veux pas qu'elles soient coupées, je les fais en varchar (200) qui est généralement beaucoup plus grande que ce dont j'ai besoin. Y a-t-il un gros problème en donnant à un champ varchar beaucoup plus de longueur que nécessaire?

Brian
la source
Une table avec une seule VARCHAR(255) utf8mb4colonne indexée avec ~ 150 000 lignes mesurait 11,5 Mo. Une table avec une VARCHAR(48) utf8mb4colonne indexée avec les mêmes données (longueur maximale 46 caractères) a utilisé 4,5 Mo. Pas vraiment une grande différence dans les requêtes, il est indexé. Mais cela s'additionne avec les E / S de requête et des choses comme les sauvegardes de base de données.
Code4R7

Réponses:

59

Non, dans le sens où si les valeurs que vous stockez dans cette colonne sont toujours (disons) inférieures à 50 caractères, déclarer la colonne comme varchar(50)ou varchar(200)a les mêmes performances.

Alex Martelli
la source
9
Pas exactement le vrai. Voir la réponse de Bill Karwin
hejdav
5
Je pense qu'une réponse comme celle-ci devrait être appuyée par des documents, des repères ou quelque chose de similaire.
Gokhan Sari
301

Il y a un impact possible sur les performances: dans MySQL, les tables temporaires et les MEMORYtables stockent une VARCHARcolonne sous la forme d'une colonne de longueur fixe, complétée à sa longueur maximale. Si vous concevez des VARCHARcolonnes beaucoup plus grandes que la plus grande taille dont vous avez besoin, vous consommerez plus de mémoire que nécessaire. Cela affecte l'efficacité du cache, la vitesse de tri, etc.

Bill Karwin
la source
33
+1. Il me semble également que certains pilotes JDBC allouent suffisamment d'espace pour la taille maximale lors de la configuration de tampons pour récupérer des lignes. Inutile de dire que cela provoque beaucoup d'angoisse et de grincements de dents quand un clown vient de faire varchar (50000) juste au cas où quelqu'un aurait un très grand nom de famille :-)
paxdiablo
21
+1. C'est un impact important et je pense que c'est la vraie réponse à cette question.
Emre Yazici
6
Cette réponse et la réponse acceptée sont toutes deux nécessaires pour comprendre la bonne réponse au PO.
kd8azz
2
En fait, lorsqu'une telle MEMORYtable est considérée comme trop volumineuse, elle est écrite sur le disque, ce qui entraîne une dégradation significative des performances.
Timo
1
Cette réponse pourrait faire avec la spécification de quels moteurs de stockage il est vrai (je note que dev.mysql.com/doc/refman/8.0/en/… indique que les tables temporaires sont toujours InnoDB à partir de MySQL 8; cela change-t-il quelque chose?) , et avec des liens vers des documents qui sauvegardent les revendications qu'il fait. D'après ce que j'ai vu de votre sortie sur Stack Exchange, je suis convaincu que vous aviez raison lorsque vous avez écrit ceci, mais les choses ont peut-être changé et les liens seraient à la fois un bon exemple pour les autres et nous aideraient à apprendre au reste d'entre nous à trouver ce genre d'informations pour nous-mêmes.
Mark Amery
14

VARCHAR est idéal pour la situation que vous décrivez, car il signifie "caractère variable" - la limite, basée sur votre exemple, serait de 200 caractères mais rien de moins est accepté et ne remplira pas la taille allouée à la colonne.

VARCHAR prend également moins d'espace - les valeurs sont stockées sous la forme d'un préfixe de longueur d'un octet ou de deux octets plus les données. Le préfixe de longueur indique le nombre d'octets dans la valeur. Une colonne utilise un octet de longueur si les valeurs ne nécessitent pas plus de 255 octets, deux octets de longueur si les valeurs peuvent nécessiter plus de 255 octets.

Pour plus d'informations sur la comparaison des types de données MySQL CHAR et VARCHAR, consultez ce lien .

Poneys OMG
la source
1
tous ceux qui s'intéressent au stockage MySQL (à propos de CHAR et VARCHAR) devraient lire le lien mentionné dans cette réponse. Merci!
Pascal
14

La taille est la performance! Plus la taille est petite, mieux c'est. Pas aujourd'hui ni demain, mais un jour, vos tables atteindront une taille en cas de sérieux goulots d'étranglement, quel que soit le design que vous avez présenté. Mais vous pouvez prévoir certains de ces goulots d'étranglement potentiels dans votre phase de conception qui sont susceptibles de se produire en premier et essayer de prolonger le temps que votre base de données fonctionnera rapidement et heureusement jusqu'à ce que vous deviez repenser votre schéma ou évoluer horizontalement en ajoutant plus de serveurs.

Dans votre cas, vous pouvez rencontrer de nombreuses pertes de performances: les grosses jointures sont presque impossibles avec de longues varcharcolonnes. L'indexation sur ces colonnes est une véritable tuerie. Votre disque doit stocker les données. Une page de mémoire peut contenir moins de lignes et les analyses de table seront beaucoup plus lentes. Il est également peu probable que le cache de requêtes vous aide ici.

Vous devez vous demander: combien d'insertions par an peuvent se produire? Quelle est la longueur moyenne? Ai-je vraiment besoin de plus de 200 caractères ou puis-je détecter cela dans le front-end de mon application, même en informant les utilisateurs de la longueur maximale? Puis-je diviser la table en une table étroite pour une indexation et une numérisation rapides et une autre pour contenir des données supplémentaires, moins fréquemment nécessaires, de taille croissante? Puis-je taper les données varchar possibles dans des catégories et ainsi extraire certaines des données dans quelques colonnes plus petites, peut-être de type int ou booléen et réduire la colonne varchar de cette façon?

Vous pouvez faire beaucoup ici. Il peut être préférable de partir d'une première hypothèse, puis de reconcevoir étape par étape en utilisant des données de performance mesurées en temps réel. Bonne chance.

Coup de coude
la source
+1 pour répertorier les options de conception et explorer l'impact. Très utile pour ma question également. stackoverflow.com/q/12083089/181638
Assad Ebrahim
5
La définition d'une longueur maximale élevée a-t-elle un impact réel sur les performances ou les performances sont-elles uniquement déterminées par la taille réelle?
poolie
5

Performance? Non. Stockage sur disque? Oui, mais c'est bon marché et copieux. À moins que votre base de données atteigne une échelle de téraoctets, vous allez probablement bien.

duffymo
la source
Il est étrange que cette réponse ait été rejetée six ans après sa publication et aucune des autres ne l'a été. Semble vindicatif et mesquin. Il n'y a rien d'incorrect dans cette réponse. Modérateurs?
duffymo
1
Comme on l'a dit, cela affecte les performances. De plus, le stockage sur disque n'est pas non plus gratuit. Une colonne plus large signifie plus de lectures / écritures de disque (et l'accès au disque est slooooooow), et aussi des index plus larges, ce qui réduit leur utilité. Les deux choses ont un impact négatif sur les performances. C'est peut-être négligeable sur une petite base de données, mais à l'échelle du gigaoctet / téraoctet, cela importera certainement, comme vous le dites. Pour une table de 100 registres, cela n'a pas d'importance.
Alejandro
5

Certains d'entre vous se trompent en pensant que a varchar(200)occupe plus de taille de table sur le disque que a varchar(20). Ce n'est pas le cas. Ce n'est que lorsque vous dépassez 255 caractères que mysql utilise un octet supplémentaire pour déterminer la longueur des varchardonnées du champ.

DCH
la source
9
Ce n'est pas le cas pour les tables et MEMORYtables temporaires .
Courses de légèreté en orbite le
4
Chaque fois que votre requête de sélection utilise une table temporaire (groupe et ordre par opérations, entre autres), elle convertira varchar (200) en char (200) et les performances en souffriront.
Jamie
1

Il peut y avoir des problèmes de performances - mais généralement pas à un niveau que la plupart des utilisateurs remarqueraient.

Lorsque la taille de chaque champ est connue à l'avance, MySQL sait exactement combien d'octets se trouvent entre chaque champ / ligne et peut avancer sans lire toutes les données. L'utilisation de caractères variables réduit cette capacité d'optimisation.

Varchar entraîne-t-il une baisse des performances en raison de la fragmentation des données?

Mieux encore, char vs varchar .

Pour la plupart des utilisations, vous serez d'accord avec l'un ou l'autre - mais il y a une différence, et pour les bases de données à grande échelle, il y a des raisons pour lesquelles vous choisiriez l'un ou l'autre.

Rizwan Kassim
la source
0

Étant varchar, plutôt que simplement char, la taille est basée sur un champ interne pour indiquer sa longueur réelle et la chaîne elle-même. Donc, utiliser varchar (200) n'est pas très différent de l'utilisation de varchar (150), sauf que vous avez le potentiel d'en stocker davantage.

Et vous devriez considérer ce qui se passe lors d'une mise à jour, lorsqu'une ligne se développe. Mais si c'est rare, alors ça devrait aller.

Rob Farley
la source
0

Selon le nom du type de données, il s'agit de VARCHAR, c'est-à-dire le stockage de données à caractères variables, le moteur mysql lui-même alloue la mémoire utilisée selon les données stockées, donc il n'y a pas de performance atteinte selon ma connaissance.

user2903114
la source
0

Vous devriez essayer d'afficher une colonne varchar de la même manière qu'une colonne char dans la plupart des scénarios et définir la longueur de manière prudente. Vous ne devez pas toujours penser au modificateur var comme à quelque chose qui a un impact sur votre prise de décision sur la longueur maximale. Cela devrait vraiment être considéré comme un indice de performance au lieu de cela que les cordes fournies seront de longueurs variables.

Ce n'est pas une directive qui doit être strictement suivie par les internes de la base de données, elle peut être complètement ignorée. Faites attention avec ceci cependant car parfois l'implémentation peut fuir (longueur et remplissage fixes par exemple) même si elle ne devrait pas dans un monde idéal.

Si vous avez un varchar (255), vous n'avez aucune garantie que, en termes de performances, il se comportera toujours différemment d'un char (255) en toutes circonstances.

Il peut sembler facile de le définir à quelque chose comme 255, 65535, etc. en conformité avec les conseils donnés dans le manuel sur les exigences de stockage. Cela donne l'impression que toute valeur comprise entre 0 (oui, c'est une chose) et 255 aura le même impact. Cependant, ce n'est pas quelque chose qui peut être entièrement garanti.

Les exigences de stockage ont tendance à être vraies ou à être un bon indicateur de moteurs de stockage persistants décents et matures en termes de stockage en ligne. Ce n'est pas un indicateur aussi fort pour des choses comme les index.

C'est parfois une question difficile, combien de temps exactement un morceau de ficelle doit-il durer pour le configurer à la limite la plus élevée que vous savez qu'il devrait être à l'intérieur, mais cela n'a aucun impact. Malheureusement, cela revient souvent à l'utilisateur de travailler et c'est vraiment quelque peu arbitraire. Vous ne pouvez pas vraiment dire de ne jamais surdimensionner une chaîne, car il peut y avoir des cas où vous n'êtes pas vraiment sûr.

Vous devez vous assurer que les requêtes MySQL génèrent une erreur lorsqu'une chaîne est trop longue plutôt que tronquée afin qu'au moins vous sachiez si elle pourrait être trop courte à cause des émissions d'erreur. Le redimensionnement des colonnes pour les agrandir ou les réduire peut être une opération DDL coûteuse, cela doit être gardé à l'esprit.

Le jeu de caractères doit également être pris en compte lorsque la longueur et les performances entrent en jeu. La longueur fait référence à cela plutôt qu'aux octets. Si vous utilisez utf8 par exemple (et non MB4), alors varchar (255) est vraiment varbinary (3 * 255). Il est difficile de savoir comment des choses comme celles-ci se dérouleront vraiment sans exécuter de tests et sans examiner en profondeur le code source / la documentation. Pour cette raison, il est possible qu'une longueur excessive ait un impact gonflé de manière inattendue. cela ne s'applique pas uniquement aux performances. Si vous avez un jour besoin de changer le jeu de caractères d'une colonne varchar en un plus grand, vous pourriez finir par atteindre une limite sans recours si vous avez autorisé la présence de chaînes longues gratuitement, ce qui aurait pu être évité. C'est normalement un problème assez spécifique, mais il se pose,

S'il s'avère que MAX (LENGTH (colonne)) est toujours <64 (par exemple s'il était décidé qu'il y aurait une limite d'entrée qui ne correspond pas à la définition de colonne) mais que vous avez varchar (255) alors il y a un il y a de fortes chances que vous utilisiez quatre fois plus d'espace que nécessaire dans certains scénarios.

Cela peut inclure:

  • Différents moteurs, certains peuvent l'ignorer complètement.
  • Les tailles de tampon, par exemple la mise à jour ou l'insertion, peuvent devoir allouer le 255 complet (bien que je n'ai pas vérifié le code source pour le prouver, ce n'est qu'une hypothèse).
  • Index, ce sera immédiatement évident si vous essayez de créer une clé composite à partir de nombreuses colonnes varchar (255).
  • Tables intermédiaires et éventuellement ensembles de résultats. Étant donné le fonctionnement des transactions, il n'est pas toujours possible pour quelque chose d'utiliser la longueur maximale réelle des chaînes dans une colonne par opposition à la limite définie.
  • Les optimisations prédictives internes peuvent prendre la longueur maximale comme entrée.
  • Changements dans les versions d'implémentation de la base de données.

En règle générale, il n'est vraiment pas nécessaire qu'un varchar soit plus long que nécessaire, que ce soit des problèmes de performances ou non, je vous recommande donc de vous en tenir à cela lorsque vous le pouvez. Faire plus d'efforts pour échantillonner la taille de vos données, appliquer une vraie limite ou découvrir la vraie limite en demandant / en recherchant est l'approche idéale.

Lorsque vous ne pouvez pas, si vous voulez faire quelque chose comme varchar (255) pour les cas de doute, je vous recommande de faire de la science. Cela peut consister à dupliquer la table, à réduire la taille de la colonne var char, puis à y copier les données à partir de l'original et à examiner la taille des données d'index / ligne (indexez également la colonne, essayez-la également comme clé primaire qui peuvent se comporter différemment dans InnoDB car les lignes sont triées par clé primaire). Au moins de cette façon, vous saurez si vous avez un impact sur les E / S, qui a tendance à être l'un des goulots d'étranglement les plus sensibles. Tester l'utilisation de la mémoire est plus difficile, il est difficile de le tester de manière exhaustive. Je recommanderais de tester les pires cas potentiels (requêtes avec beaucoup de résultats intermédiaires dans la mémoire, vérifiez avec Expliquer les grandes tables temporaires, etc.).

Si vous savez qu'il n'y aura pas beaucoup de lignes dans la table, vous n'allez pas utiliser la colonne pour les jointures, les index (en particulier composite, unique), etc., vous n'aurez probablement pas beaucoup de problèmes.

jgmjgm
la source