CHAR / VARCHAR, quel différence ???

Beaucoup de jeunes développeurs n’utilisent jamais que le VARCHAR comme type de données pour les littéraux. Mais ce type possède des inconvénients masqués. Nous allons comparer les deux afin que votre choix soit éclairé !

CHAR(n) est un type de données qui respecte de la longueur dont n caractères stockée même si la longueur du texte est inférieure à n, il y aura alors un remplissage à blanc.
Exemple :
« toto » en CHAR(12) donne :

"toto        "

VARCHAR(n) est un type de données de longueur variable avec au maximum n caractères stockée + stockage de la longueur du texte (en général sur 2 octets) et pas de remplissage à blanc.
Exemple « toto » en VARCHAR(12) donne :

04"toto"

AVANTAGES / INCONVÉNIENTS :
VARCHAR économise de l’espace si la longueur des données peut être grande et la taille du texte très fluctuante. Or plus on économise l’espace meilleures seront les performances .
Mais si la données est voisine de la taille maximale ou fais toujours la taille maximale, alors avec les 2 octets pour stocker la taille c’est le contraire qui se produit.
Par exemple pour un code postal, c’est stupide car il y aura toujours 5 caractères (en France) => VARCHAR = 7 octets, CHAR = 5 octets

En sus, la recherche d’une colonne VARCHAR est plus complexe que la recherche d’une colonne CHAR au sein de la ligne composant la table. Son accès est donc plus lent, car il faut parcourir toutes les colonnes précédentes du fait de la longueur variable. Alors qu’avec une longueur fixe, il suffit de calculer l’offset par rapport au début de la ligne pour trouver immédiatement l’emplacement du premier caractère de la colonne de type CHAR (en fait pour optimiser les accès aux données, la plupart des SGBDR constituent les lignes des tables avec les colonnes de taille fixe en premier et les colonnes de taille variable en dernier de façon à ce que le repérage des colonnes de type fixe soit immédiat.

Enfin, lors des mises à jour la fragmentation du VARCHAR peut devenir très pénalisante. En effet si j’ai stocké « toto » dans un VARCHAR(16) qui va être enchâssé dans la ligne, comment puis-je le faire passer à « taratata » dans une UPDATE ? Il n’est plus possible de la laisser à cet emplacement qui est trop court. Il va donc falloir déplacer soit la ligne complète (si la table n’est pas clusterisée) soit la colonne si la table est clusterisée, et dans tous les cas cela génère de la fragmentation qui est très préjudiciable aux performances.

Pour couronner le tout, certains SGBDR mal conçus comme MySQL, transforment les VARCHAR(n) en CHAR(n) donc de longueur fixe pour certaines opérations relationnelles comme les tris ou les groupages, ce qui fait qu’en cas de mauvais choix, et de plus avec un dimension mal adapté (exemple VARCHAR(255) partout comme je le voit souvent…) cela revient à manipuler un fort volume de données qui pénalise fortement les performances….

C’est pourquoi lorsque l’on modélise des données, il faut étudier les types de données avec soin (pas seulement pour les littéraux), en sachant quels vont être les traitements, la volumétrie, la fréquence d’accès, les recherches, la nature des mises à jour…

Hé oui, modéliser des données, c’est un métier !


--------
Frédéric Brouard, SQLpro - ARCHITECTE DE DONNÉES, http://sqlpro.developpez.com/
Expert bases de données relationnelles et langage SQL. MVP Microsoft SQL Server
www.sqlspot.com : modélisation, conseil, audit, optimisation, tuning, formation
* * * * *  Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence  * * * * *

MVP Microsoft SQL Server

5 réflexions au sujet de « CHAR / VARCHAR, quel différence ??? »

  1. Avatar de pachotpachot

    Bonjour,
    Cet article ne s’applique pas à tous les SGBD. La norme SQL définit le comportement mais le stockage est au choix de l’implémentation. Par exemple, même si Oracle retourne « toto  » pour un char(12), il sera stocké exactement de la même manière qu’un VARCHAR: les espaces ne sont pas stockés.
    Le choix ne se fait pas alors pour de questions de stockage et de performance car c’est la même chose.
    Cordialement,
    Franck.

  2. Avatar de sqlprosqlpro Auteur de l’article

    Quand une valeur de CHAR est lue, les espaces en trop sont retirés.
    Non cela n’est pas conforme. Pour le CHAR les blancs subsistent dans les IHM….

    En fait dans la norme SQL les blancs de remplissage sont toujours non significatif pour la recherche. Mais attention, ce ne sont pas toujours les blancs de droite ! En effet pour certaines langues dont le sens de lecture est inverse des langues latines (arabe par exemple) ce sont les caractères de gauche qui ne sont pas significatifs…. Donc tout dépend de la collation !

    A +

  3. Avatar de cinephilcinephil

    Si je stocke ‘Toto’ dans une colonne Nom de type CHAR(6), le SGBD complètera ‘Toto’ en ‘Toto ‘ d’après ce que tu dis.
    Que se passera t-il ensuite si je fais la requête ci-dessous ?
    SELECT des_colonnes
    FROM la_table
    WHERE Nom = ‘Toto’

    Sous MySQL, j’obtiens bien la ligne insérée, ce qui est conforme à sa documentation :
    Quand une valeur CHAR est enregistrée, elle est complété à droite avec des espaces jusqu’à atteindre la valeur fixée. Quand une valeur de CHAR est lue, les espaces en trop sont retirés.
    MySQL est-il en cela conforme à la norme ?

Laisser un commentaire