276 votes

Quels sont les cas d'utilisation pour sélectionner CHAR plutôt que VARCHAR en SQL ?

Je sais que CHAR est recommandé si toutes mes valeurs sont à largeur fixe. Mais, et alors ? Pourquoi ne pas choisir VARCHAR pour tous les champs de texte, juste pour être sûr.

389voto

Jim McKeeth Points 22637

La règle générale est de choisir CHAR si toutes les lignes sont proches de la même longueur . Choisir VARCHAR (ou NVARCHAR ) lorsque le la longueur varie de manière significative. CHAR peut également être un peu plus rapide parce que toutes les lignes sont de la même longueur.

Cela varie selon l'implémentation de la base de données, mais en général, VARCHAR (ou NVARCHAR ) utilise un ou deux octets de stockage supplémentaires (pour la longueur ou la terminaison) en plus des données proprement dites. Ainsi (en supposant que vous utilisiez un jeu de caractères d'un octet), stocker le mot "FooBar"

  • CHAR(6) \= 6 octets (pas de frais généraux)
  • VARCHAR(100) \= 8 octets (2 octets de surcharge)
  • CHAR(10) \= 10 octets (4 octets de déchets)

Le résultat est le suivant CHAR peut sea plus rapide et plus efficace en termes d'espace pour les données de longueur relativement identique (à deux caractères près).

Nota : Microsoft SQL a 2 octets de surcharge pour un VARCHAR. Cela peut varier d'une base de données à l'autre, mais en général, il y a au moins 1 octet de surcharge nécessaire pour indiquer la longueur ou la fin de vie d'un VARCHAR.

Comme l'a souligné Gaven dans les commentaires : Les choses changent lorsqu'il s'agit de caractères multi-octets et c'est un cas où VARCHAR devient un bien meilleur choix.

Une remarque sur la longueur déclarée de la VARCHAR : Parce qu'il stocke la longueur du contenu réel, il n'y a pas de perte de longueur inutilisée. Ainsi, en stockant 6 caractères dans _VARCHAR(6), VARCHAR(100), o VARCHAR(MAX)_ utilise la même quantité de mémoire. Pour en savoir plus sur les différences entre l'utilisation de VARCHAR(MAX) . Vous déclarez un maximum size en VARCHAR pour limiter la quantité stockée.

Dans les commentaires AlwaysLearning a souligné que la Documentation Microsoft Transact-SQL semblent dire le contraire. Je pense qu'il s'agit d'une erreur ou, du moins, que la documentation n'est pas claire.

20 votes

Une autre raison est l'éclatement et la fragmentation des pages. J'avais une table avec un PK IDEN qui était fragmentée à 99% à cause des fractionnements de page sur les colonnes varchar. Il s'agissait d'une table très active et, de par la nature de l'application, une nouvelle ligne vide était créée puis remplie. Char a résolu le problème de fragmentation.

12 votes

@Jim McKeeth -- ces calculs ne sont vrais que si vous utilisez le charset latin1. Puisque la plupart des gens devraient utiliser utf8 de nos jours, vos colonnes CHAR vont utiliser en moyenne trois fois plus d'espace qu'un VARCHAR qui stocke principalement des caractères dans le plan multilingue de base.

0 votes

@GavinTowey J'ai dit que cela supposait un jeu de caractères d'un octet. Êtes-vous en train de dire que l'UTF8 prend 3x plus d'espace dans CHAR que dans VARCAR ? Ainsi, 3 lettres dans CHAR représentent 9 octets, et 3 dans VARCAR ?

69voto

Ethan Post Points 1369

Si vous travaillez avec moi et que vous travaillez avec Oracle, je vous demanderai probablement d'utiliser varchar dans presque toutes les circonstances. L'hypothèse selon laquelle char utilise moins de puissance de traitement que varchar C'est peut-être vrai... pour l'instant... mais les moteurs de base de données s'améliorent avec le temps et ce type de règle générale est en passe de devenir un "mythe".

Autre chose : je n'ai jamais vu de problème de performance parce que quelqu'un avait décidé d'opter pour le varchar . Vous ferez un bien meilleur usage de votre temps en écrivant du bon code (moins d'appels à la base de données) et du code SQL efficace (comment fonctionnent les index, comment l'optimiseur prend-il ses décisions, pourquoi le code SQL est il utilisé pour la gestion de la base de données). exists plus rapide que in habituellement...).

Dernière réflexion : J'ai constaté toutes sortes de problèmes liés à l'utilisation de CHAR Il s'agit par exemple de personnes qui cherchent '' alors qu'elles devraient chercher '', de personnes qui cherchent 'FOO' alors qu'elles devraient chercher 'FOO (plusieurs espaces ici)', de personnes qui ne coupent pas les blancs à la fin, ou de bugs avec Powerbuilder qui ajoute jusqu'à 2000 blancs à la valeur qu'il renvoie à partir d'une procédure Oracle.

20 votes

Je ne suis pas tout à fait d'accord avec votre premier paragraphe, car char peut fournir un indice qui pourrait être utile aux optimiseurs, même futurs, et il peut aider à communiquer l'intention de la colonne. Mais +1 pour votre troisième paragraphe. Je déteste tous les espaces supplémentaires. Un champ devrait simplement stocker ce que j'y mets sans tout ce rembourrage [explicatif]. En fait, je n'utilise que char si toutes les données doivent avoir exactement la même longueur, ni plus ni moins, maintenant et pour toujours. C'est très rare, bien sûr, et il s'agit généralement d'un char(1).

0 votes

Char fournit également des indications aux analystes et aux développeurs... cette chose fait x nombre de chars.... S'ils envisagent de le sérialiser dans un autre format, cela peut être utile. (J'ai été obligé de stocker une somme de contrôle md5 dans un caractère dans mssql qui n'avait pas de type uuid... et je n'ai jamais voulu quelque chose < 32 octets... j'ai également mis une contrainte sur la colonne).

32voto

Hank Gay Points 36173

En plus des avantages en termes de performance, CHAR peut être utilisé pour indiquer que toutes les valeurs devrait être de même longueur, par exemple une colonne pour les abréviations des États américains.

0 votes

Ou codes de pays - peut aider à faire la distinction entre l'utilisation d'une abréviation de code de pays à 2 ou 3 caractères.

0 votes

S'il s'agit vraiment d'une longueur fixe, il devrait y avoir une contrainte qui l'impose. Bien que si vous utilisez CHAR vous devrez vous assurer que votre contrainte ne comporte pas de rembourrage.

19voto

Jarrett Meyer Points 11147

Char est un peu plus rapide, donc si vous avez une colonne dont vous SAVEZ qu'elle sera d'une certaine longueur, utilisez char. Par exemple, stocker (M)ale/(F)emale/(U)nknown pour le sexe, ou 2 caractères pour un état américain.

5 votes

Je ne suis pas sûr que ce soit une bonne réponse, car un ENUM serait généralement plus logique, bien que je ne sois pas sûr que ce type soit largement supporté (en dehors de MySQL).

0 votes

Il me semble que l'ensemble des états n'est pas nécessairement immuable, donc char(2) semble beaucoup plus approprié qu'une énumération.

1 votes

@Bobby Jack - Je ne connais pas les détails spécifiques de l'implémentation d'un enum SQL particulier, mais gardez à l'esprit qu'un enum stocké sous la forme d'un entier de 4 octets peut nécessiter plus d'espace qu'une colonne char(1) ou char(2) avec les mêmes données. D'une certaine manière, les énumérations sont plus logiques en termes d'interprétation, et cela peut être convaincant, mais dans un système SGBDR, tout est abstrait à un certain niveau et soumis aux prédicats définis pour les tables.

12voto

Données à stocker : "ABCD"


Char(4) prend 4b

varchar(4) prend 6b

o

Char(40) prend 40b

varchar(40) prend 6b

o

Char(400) prend 400b

varchar(400) prend 6b

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X