J'ai un contacts
tableau qui contient des domaines tels que postcode
, first name
, last name
, town
, country
, phone number
etc, qui sont tous définis comme VARCHAR(255)
même si aucun de ces domaines ne viendra jamais près d'avoir 255 caractères. (Si vous vous posez la question, c'est de cette façon parce que les migrations Ruby on Rails mappent les champs String VARCHAR(255)
par défaut et je n'ai jamais pris la peine de le remplacer).
Étant donné que VARCHAR ne stockera que le nombre de caractères réels du champ (ainsi que la longueur du champ), y a-t-il un avantage distinct (performance ou autre) à utiliser, par exemple, VARCHAR(16)
over VARCHAR(255)
?
En outre, la plupart de ces champs ont des index sur eux. Une taille VARCHAR plus grande sur le champ affecte-t-elle la taille ou les performances de l'index?
Pour info, j'utilise MySQL 5.
Réponses:
Dans le stockage, il
VARCHAR(255)
est assez intelligent pour stocker uniquement la longueur dont vous avez besoin sur une ligne donnée, contrairement àCHAR(255)
ce qui stockerait toujours 255 caractères.Mais puisque vous avez tagué cette question avec MySQL, je mentionnerai une astuce spécifique à MySQL: lorsque les lignes sont copiées de la couche du moteur de stockage vers la couche SQL, les
VARCHAR
champs sont convertis enCHAR
pour gagner l'avantage de travailler avec des lignes de largeur fixe. Ainsi, les chaînes en mémoire sont remplies à la longueur maximale de votreVARCHAR
colonne déclarée .Lorsque votre requête génère implicitement une table temporaire, par exemple lors du tri ou
GROUP BY
, cela peut utiliser beaucoup de mémoire. Si vous utilisez beaucoup deVARCHAR(255)
champs pour des données qui n'ont pas besoin d'être aussi longues, cela peut rendre la table temporaire très volumineuse.Vous voudrez peut-être aussi savoir que ce comportement de «remplissage» signifie qu'une chaîne déclarée avec le jeu de caractères utf8 remplit jusqu'à trois octets par caractère même pour les chaînes que vous stockez avec un contenu à un octet (par exemple, les caractères ascii ou latin1). Et de même, le jeu de caractères utf8mb4 entraîne le remplissage de la chaîne à quatre octets par caractère en mémoire.
Ainsi, un
VARCHAR(255)
in utf8 stockant une chaîne courte comme "No opinion" prend 11 octets sur le disque (dix caractères de jeu de caractères inférieurs, plus un octet pour la longueur) mais cela prend 765 octets en mémoire, et donc dans des tables temporaires ou des résultats triés.J'ai aidé les utilisateurs de MySQL qui, sans le savoir, ont fréquemment créé des tables temporaires de 1,5 Go et ont rempli leur espace disque. Ils avaient beaucoup de
VARCHAR(255)
colonnes qui stockaient en pratique des chaînes très courtes.Il est préférable de définir la colonne en fonction du type de données que vous souhaitez stocker. Il présente des avantages pour appliquer les contraintes liées aux applications, comme d'autres l'ont mentionné. Mais il a les avantages physiques d'éviter le gaspillage de mémoire que j'ai décrit ci-dessus.
Il est difficile de savoir quelle est l'adresse postale la plus longue, bien sûr, c'est pourquoi de nombreuses personnes choisissent une
VARCHAR
adresse longue qui est certainement plus longue que n'importe quelle adresse. Et 255 est habituel car c'est la longueur maximale de aVARCHAR
pour laquelle la longueur peut être codée avec un octet. C'était aussi laVARCHAR
longueur maximale de MySQL antérieure à 5.0.la source
255
c'était utilisé pour que la longueur de la chaîne puisse tenir dans un seul octetOutre les considérations de taille et de performances liées à la définition de la taille d'un varchar (et peut-être plus important, car le stockage et le traitement deviennent moins chers chaque seconde), l'inconvénient d'utiliser varchar (255) «juste parce que» est une réduction de l'intégrité des données .
La définition de limites maximales pour les chaînes est une bonne chose à faire pour éviter que des chaînes plus longues que prévu n'entrent dans le SGBDR et ne provoquent des dépassements de mémoire tampon ou des exceptions / erreurs plus tard lors de la récupération et de l'analyse des valeurs de la base de données qui sont plus longues (plus d'octets) que prévu.
Par exemple, si vous avez un champ qui accepte des chaînes de deux caractères pour les abréviations de pays, vous n'avez aucune raison concevable d'attendre de vos utilisateurs (dans ce contexte, les programmeurs) qu'ils saisissent les noms de pays complets. Puisque vous ne voulez pas qu'ils entrent "Antigua-et-Barbuda" (AG) ou "Heard Island et McDonald Islands" (HM), vous ne l'autorisez pas au niveau de la base de données. En outre, il est probable que certains programmeurs ont pas encore RTFMed la documentation de conception ( qui existe sûrement ) de ne pas savoir faire cela.
Définissez le champ pour accepter deux caractères et laissez le SGBDR le traiter (soit gracieusement en tronquant, soit sans grâce en rejetant leur SQL avec une erreur).
Exemples de données réelles qui n'ont aucune raison de dépasser une certaine longueur:
Etc...
Prenez le temps de réfléchir à vos données et à leurs limites. Si vous êtes architecte, développeur ou programmeur, c'est votre travail , après tout.
En utilisant un varchar (n) au lieu de varchar (255), vous éliminez le problème où les utilisateurs (utilisateurs finaux, programmeurs, autres programmes) entrent des données inopinément longues qui reviendront hanter votre code plus tard.
Et je n'ai pas dit que vous ne devriez pas également implémenter cette restriction dans le code de logique métier utilisé par votre application.
la source
the design documentation (which surely exists)
Hah. : DJe suis d'accord. Une attention particulière aux détails est une douleur dans le cou et a une valeur limitée.
Il était une fois, le disque était une denrée précieuse et nous avions l'habitude de suer les balles pour l'optimiser. Le prix du stockage a été divisé par 1 000, ce qui rend le temps passé à presser chaque octet moins précieux.
Si vous n'utilisez que des champs CHAR, vous pouvez obtenir des lignes de longueur fixe. Cela peut économiser une reformulation réelle du disque si vous avez choisi des tailles précises pour les champs. Vous pouvez obtenir des données plus denses (moins d'E / S pour les analyses de table) et des mises à jour plus rapides (plus facile à localiser les espaces ouverts dans un bloc pour les mises à jour et les insertions).
Cependant, si vous surestimez vos tailles ou si vos tailles de données réelles sont variables, vous finirez par perdre de l'espace avec les champs CHAR. Les données seront moins densément compactées (ce qui entraînera plus d'E / S pour les grandes récupérations).
En règle générale, les avantages en termes de performances de la tentative de mettre une taille sur des champs variables sont mineurs. Vous pouvez facilement comparer en utilisant VARCHAR (255) par rapport à CHAR (x) pour voir si vous pouvez mesurer la différence.
Cependant, parfois, j'ai besoin de fournir un indice «petit», «moyen», «grand». J'utilise donc 16, 64 et 255 pour les tailles.
la source
De nos jours, je ne peux pas imaginer que cela compte vraiment plus.
L'utilisation de champs de longueur variable entraîne une surcharge de calcul, mais avec les excès des processeurs actuels, cela ne vaut même pas la peine d'être pris en compte. Le système d'E / S est si lent que les coûts de calcul pour gérer les varchars sont effectivement inexistants. En fait, le prix d'un varchar est probablement un gain net sur la quantité d'espace disque économisé en utilisant des champs de longueur variable sur des champs de longueur fixe. Vous avez probablement une plus grande densité de lignes.
Maintenant, la complexité des champs varchar est que vous ne pouvez pas localiser facilement un enregistrement via son numéro d'enregistrement. Lorsque vous avez une taille de ligne de longueur fixe (avec des champs de longueur fixe), il est trivial de calculer le bloc de disque vers lequel pointe un identifiant de ligne. Avec une taille de ligne de longueur variable, ce genre de sortie par la fenêtre.
Donc, maintenant, vous devez maintenir une sorte d'index de numéro d'enregistrement, comme toute autre clé primaire, OU vous devez créer un identifiant de ligne robuste qui encode les détails (tels que le bloc, etc.) dans l'identifiant. Si vous faites cela, cependant, l'ID devrait être recalculé si jamais la ligne est déplacée sur un stockage persistant. Ce n'est pas grave, il suffit de réécrire toutes les entrées d'index et de s'assurer que vous a) ne l'exposez jamais au consommateur ou b) n'affirmez jamais que le nombre est fiable.
Mais puisque nous avons des champs varchar aujourd'hui, la seule valeur de varchar (16) par rapport à varchar (255) est que la base de données appliquera la limite de 16 caractères sur varchar (16). Si le modèle de base de données est censé être réellement représentatif du modèle de données physique, alors la longueur des champs peut être intéressante. Si, cependant, il s'agit simplement d'un "stockage" plutôt que d'un "modèle ET stockage", il n'y a aucun besoin.
Ensuite, vous devez simplement discerner entre un champ de texte indexable (tel que varchar) et quelque chose qui ne l'est pas (comme un champ de texte ou CLOB). Les champs indexables ont tendance à avoir une limite de taille pour faciliter l'index, contrairement aux champs CLOB (dans des limites raisonnables).
la source
D'après mon expérience, si vous autorisez un type de données de 255 caractères, un utilisateur stupide (ou un testeur expérimenté) le remplira.
Ensuite, vous rencontrez toutes sortes de problèmes, y compris l'espace que vous accordez à ces champs dans les rapports et les affichages à l'écran dans votre application. Sans parler de la possibilité de dépasser la limite par ligne pour les données de votre base de données (si vous aviez plus de quelques-uns de ces 255 champs de caractères).
Il est beaucoup plus facile de choisir une limite raisonnable au début, puis de l'appliquer via l'application et la base de données.
la source
C'est une bonne pratique de n'allouer qu'un peu plus ce dont vous avez besoin. Les numéros de téléphone n'iraient jamais aussi loin.
Une des raisons est que si vous ne validez pas contre des entrées volumineuses, quelqu'un utilisera sans aucun doute tout ce qu'il y a. Ensuite, vous pourriez manquer d'espace dans votre rangée. Je ne suis pas sûr de la limite de MySQL, mais 8060 est la taille maximale des lignes dans MS SQL.
Un défaut plus normal serait de 50 imho, puis augmenterait là où le besoin le prouve.
la source
Dans un contexte mysql, cela peut devenir important lorsque vous travaillez avec des index sur lesdites colonnes varchar, car mysql a un max. limite de 767 octets par ligne d'index.
Cela signifie que lorsque vous ajoutez un index sur plusieurs colonnes varchar 255, vous pouvez atteindre cette limite assez rapidement / encore plus rapidement sur les colonnes utf8 ou utf8mb4, comme indiqué dans les réponses ci-dessus
la source