web-dev-qa-db-fra.com

Incidences sur les performances des tailles MySQL VARCHAR

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 juste pour vous assurer de ne pas manquer de place?

46
BenV

Vous devez comprendre les compromis de l'utilisation de CHAR vs VARCHAR

Avec les champs CHAR, ce que vous allouez est exactement ce que vous obtenez. Par exemple, CHAR (15) alloue et stocke 15 octets, quelle que soit la façon dont vous placez les caractères 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 en fait dynamiquement jusqu'à 16 octets, jusqu'à 15 pour les données et, au moins, 1 octet supplémentaire pour stocker la longueur des données. Si vous avez la chaîne "bonjour" à stocker qui prendra 6 octets, pas 5. La manipulation de chaîne doit toujours effectuer une certaine forme de vérification de 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. Indexation des colonnes CHAR ou VARCHAR

TRADEOFF # 1

De toute évidence, VARCHAR détient l'avantage, car les données de longueur variable produiraient des lignes plus petites et donc des fichiers physiques plus petits.

TRADEOFF # 2

Étant donné que les champs CHAR nécessitent moins de manipulation de chaînes en raison de largeurs de champ fixes, les recherches d'index sur le 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 réalisé quelque chose de merveilleux sur une table MyISAM pour le prouver. L'exemple du livre a fait quelque chose comme ceci:

ALTER TABLE tblname ROW_FORMAT=FIXED;

Cette directive force les VARCHAR à se comporter comme des CHAR. Je l'ai fait lors de mon précédent travail en 2007 et j'ai pris une table de 300 Go et accéléré les recherches d'index de 20%, sans rien changer d'autre. Cela a fonctionné comme publié. Cependant, il a produit une table presque double, mais cela revient simplement au compromis n ° 1.

Vous pouvez analyser les données stockées pour voir ce que MySQL recommande pour la définition des colonnes. Exécutez simplement ce qui suit sur 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 champ 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 est au maximum de 15 caractères (xxx.xxx.xxx.xxx). Je sauterais directement à CHAR (15) en un clin d'œil car les longueurs des adresses IP ne varieront pas beaucoup et la complexité supplémentaire de la manipulation des chaînes contrôlée par un octet supplémentaire. Vous pouvez toujours effectuer une ANALYSE DE PROCÉDURE () sur 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 bonne planification. Avec une grande puissance vient une grande responsabilité (cliché mais vrai)

30
RolandoMySQLDBA

La réponse à cela 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, GROUP BY instructions), la longueur totale 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 implémenter un varchar approprié.

Pour (2) j'admets que le protocole de fil n'est pas quelque chose que je connais intimement, mais le conseil général ici est d'essayer et d'appliquer au moins un effort minimal pour deviner la longueur.

13
Morgan Tocker

La plupart des réponses dans ce fil sont cinq huit ans, écrit avant InnoDB et utf8 étaient des valeurs par défaut. Alors, je vais recommencer ...

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

  • TEXT/BLOB colonnes récupérées, même TINYTEXT.
  • VARCHAR plus grand qu'un certain montant, probablement 512 dans la version actuelle.

Notez également que VARCHARs est transformé en CHARs. (8.0 modifie cela.) Ainsi, VARCHAR(255) avec un CHARACTER SET utf8 S'étend à 765 octets, quel que soit le contenu de la colonne. Ensuite, cela pourrait être déclenché:

  • Si la table MEMORY devient plus grande que max_heap_table_sizeotmp_table_size, Elle sera convertie en MyISAM et potentiellement renversée sur le disque.

Ainsi, VARCHAR(25) est plus susceptible de rester MEMORY, donc d'être plus rapide. (255) N'est pas aussi bon et (64000) Est mauvais.

(À l'avenir, les tables temporaires seront probablement InnoDB, et une partie de cette réponse devra être révisée.)

11
Rick James

Une colonne varchar de cette taille rend les requêtes sur la table entière plus susceptibles d'utiliser des tables temporaires. Selon le livre MySQL High Performance. 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 regarde la taille de la ligne en fonction de la définition de la table, ce qui signifie que pour la vitesse, il n'essaie pas de voir la quantité de caractères de 64 Ko vous utilisez réellement. C'est pourquoi les auteurs recommandent de ne pas étendre cette définition bien au-delà des valeurs réelles possibles qui iraient dans la colonne. De toute évidence, 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 encouru des pénalités d'E/S que vous auriez pu éviter.

6
TechieGurl

Je crois comprendre que les petits champs peuvent être inclus directement dans l'index, alors que les plus longs ne le peuvent pas. En raison de cette limitation, si vous voulez que les chaînes soient indexables, je dirais qu'elles sont plus courtes. Sinon, non, comme ils sont tous deux varchar, les opérations comme le tri ou la comparaison fonctionneront en un temps identique, que les champs soient 25 ou MAX.

5
jcolebrand

assurez-vous de ne pas manquer de place

Cette phrase implique que vous posiez la question parce que vous n'êtes pas sûr des données que vous stockerez dans la base de données. Si c'est vrai, vous serez bien servi pour le savoir dès que possible, car vous en aurez besoin pour la planification de la capacité. Par exemple, si vous obtenez des éléments de données de 7 000 caractères, vous devez le savoir, car cela aurait des conséquences sur les performances de tout SGBD.

Cela dit, je préfère avoir des tailles de colonnes liées au contenu attendu. Par exemple, un numéro de téléphone ne dépassera probablement pas 50 caractères, même si vous incluez un code de pays et une extension. De même, un code postal ou Zip sera très probablement de 20 caractères ou moins.

3
Larry Coleman