Conséquences sur les performances des tailles MySQL VARCHAR

45

Existe-t-il une différence de performances dans MySQL entre les tailles de varchar? Par exemple, varchar(25)et varchar(64000). Sinon, y a-t-il une raison pour ne pas déclarer tous les varchars avec la taille maximale afin de ne pas manquer de place?

BenV
la source
3
+1 cette question s'applique de la même manière à tous les SGBD. Mon observation de nombreuses tailles de varchar ont tendance à augmenter.
bernd_k
5
Pas MySQL, mais cet article de blog par Depesz peut répondre à votre question pour PostgreSQL .
Xenoterracide

Réponses:

29

Vous devez réaliser les compromis liés à l'utilisation de CHAR vs VARCHAR.

Avec les champs CHAR, ce que vous allouez correspond exactement à ce que vous obtenez. Par exemple, CHAR (15) alloue et stocke 15 octets, quelle que soit la manière dont les caractères sont placés dans le champ. La manipulation des chaînes est simple et directe car la taille du champ de données est totalement prévisible.

Avec les champs VARCHAR, vous obtenez une histoire complètement différente. Par exemple, VARCHAR (15) alloue de manière dynamique jusqu'à 16 octets, jusqu'à 15 pour les données et au moins un octet supplémentaire pour stocker la longueur des données. Si vous avez la chaîne 'hello' à stocker qui prendra 6 octets, pas 5. La manipulation de chaîne doit toujours effectuer une vérification de la longueur dans tous les cas.

Le compromis est plus évident lorsque vous faites deux choses:
1. Stocker des millions ou des milliards de lignes
2. Indexer des colonnes qui sont CHAR ou VARCHAR

TRADEOFF # 1

De toute évidence, VARCHAR présente l'avantage, car les données de longueur variable produiraient des lignes plus petites et, par conséquent, des fichiers physiques plus petits.

TRADEOFF # 2

Étant donné que les champs CHAR nécessitent moins de manipulation de chaîne en raison de leur largeur fixe, les recherches d'index par rapport au champ CHAR sont en moyenne 20% plus rapides que celles des champs VARCHAR. Ce n'est pas une conjecture de ma part. Le livre MySQL Database Design and Tuning a prouvé quelque chose de merveilleux sur une table MyISAM. L'exemple dans le livre a quelque chose comme:

ALTER TABLE tblname ROW_FORMAT=FIXED;

Cette directive oblige les VARCHAR à se comporter comme des CHAR. En 2007, lors de mon travail précédent, je m'étais occupé de cette tâche en prenant une table de 300 Go et en accélérant les recherches d'index de 20%, sans rien changer d'autre. Cela a fonctionné comme publié. Cependant, il a produit une table presque deux fois plus grande, mais cela revient tout simplement au compromis # 1.

Vous pouvez analyser les données stockées pour voir ce que MySQL recommande pour la définition des colonnes. Il suffit de lancer ce qui suit contre n’importe quelle table:

SELECT * FROM tblname PROCEDURE ANALYSE();

Cela traversera la table entière et recommandera des définitions de colonne pour chaque colonne en fonction des données qu'elle contient, des valeurs de champ minimales, des valeurs de champs maximales, etc. Parfois, il suffit de faire preuve de bon sens lors de la planification de CHAR vs VARCHAR. Voici un bon exemple:

Si vous stockez des adresses IP, le masque d'une telle colonne contient au maximum 15 caractères (xxx.xxx.xxx.xxx). Je sauterais directement dans CHAR (15) car les longueurs d'adresses IP ne varieraient pas beaucoup et la complexité supplémentaire de la manipulation de chaîne contrôlée par un octet supplémentaire. Vous pouvez toujours faire une PROCEDURE ANALYSE () avec une telle colonne. Il peut même recommander VARCHAR. Mon argent serait toujours sur CHAR sur VARCHAR dans ce cas.

Les problèmes CHAR vs VARCHAR ne peuvent être résolus que par une planification appropriée. Avec un grand pouvoir vient une grande responsabilité (cliché mais vrai)

RolandoMySQLDBA
la source
4
Si vous stockez des adresses IP, je ne vois aucune raison de les stocker autrement que comme un int. C'est tout ce qu'une adresse IP est. Beaucoup de langues ont une sorte de fonction ip2int. Si vous voulez que le convienence d'un appel de ligne de commande , il est pas difficile de faire une procédure stockée pour convertir ABCD: Un pow (256,3) + b Pow (256,2) + c * 256 + d
atxdba
1
Err plus au point, je suppose que mysql a sa propre fonction ip2int: INET_ATON
atxdba
3
@atxdba: Le but de ma réponse est d'utiliser simplement CHAR vs VARCHAR. J'utilise juste IP comme exemple car sa taille de caractère est plus proche de 15. Ainsi, arrondir une taille de CHAR stable en faveur de VARCHAR n'est qu'un exemple pour illustrer la question elle-même. Votre commentaire sur les meilleures façons de représenter les adresses IP est tout à fait valable et logique.
RolandoMySQLDBA
CHAR (15) alloue 15 caractères , pas d' octets . Pour utf8, c'est 45 octets .
Rick James
2
Bien que ce soit une bonne réponse à propos de la comparaison CHAR / VARCHAR, la question portait sur différentes tailles de VARCHAR.
Collectionneur
13

La réponse à cette question est en fait assez complexe. La version courte: il y a une différence .

  1. Lors de la création de tables temporaires pour filtrer les résultats (par exemple, des GROUP BYinstructions), toute la longueur sera allouée.

  2. Le protocole filaire (envoi de lignes au client) allouera probablement la plus grande longueur.

  3. Le moteur de stockage peut / peut ne pas mettre en œuvre un varchar approprié.

Pour (2), je reconnais que le protocole filaire n’est pas quelque chose que je connais très bien, mais le conseil général est d’essayer d’appliquer au moins un effort minimal pour deviner la longueur.

Morgan Tocker
la source
À noter. MySQL 5.7 peut contenir des valeurs dans le tampon de tri (longueur variable). Expliqué plus en détail ici: mysqlserverteam.com/…
Morgan Tocker
9

La plupart des réponses dans ce fil datent de 5 ans et ont été écrites avant que InnoDB et utf8 ne soient par défaut. Alors, laissez-moi recommencer ...

Lorsqu'une requête a besoin d'une table temporaire interne, elle tente d'utiliser une MEMORYtable. Mais MEMORY ne peut pas être utilisé si

  • TEXT/ BLOBcolonnes en cours de récupération, même pas TINYTEXT.
  • VARCHAR plus gros qu'une certaine quantité, probablement 512 dans la version actuelle.

Notez également que VARCHARssont transformés en CHARs. Donc, VARCHAR(255)avec une CHARACTER SET utf8extension à 765 octets, quel que soit le contenu de la colonne. Ensuite, cela pourrait être déclenché:

  • Si la MEMORYtable devient plus grande que l'un max_heap_table_size ou l' autre tmp_table_size, elle sera convertie en MyISAM et potentiellement déversée sur le disque.

Donc, VARCHAR(25)est plus susceptible de rester MEMORY, donc être plus rapide. (255)n'est pas aussi bon, et (64000)c'est mauvais.

(Dans l’avenir, les tables temporaires le seront probablement InnoDBet une partie de cette réponse devra être révisée.)

Rick James
la source
6

Une colonne varchar de cette taille rend les requêtes sur l'ensemble de la table plus susceptibles d'utiliser des tables temporaires. Selon le livre High Performance MySQL. Lorsque l'optimiseur essaie de voir s'il peut exécuter cette requête en mémoire ou s'il a besoin d'une table temporaire, il examine la taille de la ligne en fonction de la définition de la table, ce qui signifie que, pour des raisons de rapidité, il ne recherche pas la quantité de caractères de 64 Ko. vous utilisez réellement. C'est pourquoi les rédacteurs recommandent de ne pas élargir cette définition au-delà des valeurs possibles qui figureraient dans la colonne. Évidemment, si vous vous configurez pour plus de requêtes entrant dans les tables temporaires (même si la taille réelle des données peut tenir dans la RAM), vous avez maintenant subi des pénalités d’entrée / sortie que vous auriez pu éviter.

TechieGurl
la source
C'est une perspective très fraîche. Si vous faites référence à ce livre ( amazon.com/MySQL-High-Availability-Building-Centers/dp/… ), veuillez indiquer le numéro de la page du livre dans votre réponse, car j’aimerais le lire. +1 !!!
RolandoMySQLDBA
Silly me… High PERFORMANCE pas disponible: amazon.com/High-Performance-MySQL-Optimization- Replication/dp/…… numéro de page est 236/237 Il explique en quoi la générosité dans la définition d'une colonne varchar peut être imprudente. Gardez cependant à l'esprit que ce livre a été écrit à la sortie de la version 5.1. Une troisième édition paraîtra l'année prochaine pour inclure tous les BIG changements dans la version 5.5, alors cela changera peut-être :)
TechieGurl
La page 236 mentionne une collation appartenant à des jeux de caractères particuliers. Cela pourrait être assez désagréable pour VARCHAR. Sur la page 237, Paramètres pour les communications client / serveur, ainsi que la Figure 5-5 à la page 238, indiquent une autre raison. Le processus de traduction des jeux de caractères dans les deux sens. Encore une fois, une nouvelle aventure pour VARCHAR.
RolandoMySQLDBA
Pour clarifier, même si cette section ne dit pas clairement que MySQL va créer une taille, nous savons que lorsqu'une opération a besoin d'une table temporaire, cette table est dans MEMORY Engine et THAT stocke toujours les types de chaînes dans des blocs de correctifs. La définition peut faire en sorte que la table temporaire MEMORY nécessaire soit
enregistrée
@RolandoMySQLDBA. Eh oui… ça aussi… le classement devient aussi un facteur ici (surtout si vous utilisez UTF-8 et que vous avez des caractères non latins) et que tout vous tue quand vous manipulez une table de moteur de mémoire et vous permet d'
accélérer la lecture
5

Je crois comprendre que les champs plus petits peuvent être inclus directement dans l’index, alors que les champs les plus longs ne le peuvent pas. En raison de cette limitation, si vous souhaitez que les chaînes puissent être indexées, je dirais de les garder plus courtes. Sinon, non, étant donné que les deux sont varchar, alors les opérations telles que le tri ou la comparaison fonctionnent dans le même temps, que les champs soient 25 ou MAX.

jcolebrand
la source
3

assurez-vous de ne pas manquer de place

Cette phrase implique que vous posez la question parce que vous n'êtes pas sûr des données que vous allez stocker dans la base de données. Si cela est vrai, vous aurez tout intérêt à le savoir dès que possible, car vous en aurez besoin pour la planification de la capacité. Si vous souhaitez obtenir des éléments de données contenant 7 000 caractères, par exemple, vous devez le savoir, car cela aurait des conséquences en termes de performances pour tout SGBD.

Cela dit, je préfère avoir des tailles de colonne liées au contenu attendu. Par exemple, il est peu probable qu'un numéro de téléphone ait plus de 50 caractères, même si vous incluez un indicatif de pays et un numéro de poste. De même, un code postal ou un code postal sera probablement composé de 20 caractères ou moins.

Larry Coleman
la source