Une valeur de colonne vide occupe-t-elle le même espace de stockage qu'une valeur de colonne remplie?

16

J'ai un tableau avec 2 colonnes. Le type des deux colonnes est défini sur varchar(38). Si je crée une ligne avec une valeur vide pour l'une des colonnes, cela prendra-t-il le même espace de stockage que si la valeur n'était pas vide?

En d'autres termes, MySQL réservera-t-il de l'espace de stockage pour la colonne (selon son type) lors de la création d'une ligne?

Haris ur Rehman
la source

Réponses:

11

À partir de la structure de lignes physiques Innodb, puce n ° 7 sous REDUNDANT ROW_FORMAT

Une valeur SQL NULL réserve un ou deux octets dans le répertoire d'enregistrement. En plus de cela, une valeur SQL NULL réserve zéro octet dans la partie données de l'enregistrement si elle est stockée dans une colonne de longueur variable . Dans une colonne de longueur fixe, il réserve la longueur fixe de la colonne dans la partie données de l'enregistrement. La réservation de l'espace fixe pour les valeurs NULL permet de mettre à jour la colonne de NULL vers une valeur non NULL sans provoquer de fragmentation de la page d'index.

À partir de la structure de lignes physiques Innodb, puce n ° 2 sous COMPACT ROW_FORMAT

La partie de longueur variable de l'en-tête d'enregistrement contient un vecteur de bits pour indiquer les colonnes NULL. Si le nombre de colonnes de l'index pouvant être NULL est N, le vecteur binaire occupe les octets CEILING (N / 8) . (Par exemple, s'il existe entre 9 et 15 colonnes pouvant être NULL, le vecteur de bits utilise deux octets.) Les colonnes NULL n'occupent pas d'espace autre que le bit dans ce vecteur . La partie de longueur variable de l'en-tête contient également les longueurs des colonnes de longueur variable. Chaque longueur prend un ou deux octets, selon la longueur maximale de la colonne. Si toutes les colonnes de l'index ne sont PAS NULES et ont une longueur fixe, l'en-tête d'enregistrement n'a pas de partie de longueur variable.

Sur la base de ces puces, voici ce qu'une NULLvaleur prend pour le stockage d'une colonne

  • longueur variable: une valeur NULL ne prend aucun stockage dans la ligne elle-même
  • longueur fixe: occupe l'espace réservé

Maintenant, vous devez décider entre utiliser CHAR et VARCHAR en raison de ce que le premier point a fait ressortir

La réservation de l'espace fixe pour les valeurs NULL permet de mettre à jour la colonne de NULL vers une valeur non NULL sans provoquer de fragmentation de la page d'index

Cela empêchera toute fragmentation d'une ligne qui descendra une fois les données non NULL stockées. C'est quelque chose que j'ai discuté auparavant en ce qui concerne MyISAM: Voir mon ancien article Quel est l'impact sur les performances de l'utilisation de CHAR vs VARCHAR sur un champ de taille fixe? .

RolandoMySQLDBA
la source
Salut Rolando, il y a un autre élément que j'ai oublié de mentionner, la différence d'allocation de mémoire entre une déclaration de type varchar (5) et varchar (100). Ou vraiment la pénalité encourue par la surallocation.
Craig Efrein
@CraigEfrein Vous devez absolument ajouter l'allocation de mémoire à votre réponse. (BTW j'ai déjà voté pour votre réponse)
RolandoMySQLDBA
1
La pénalité pour surallocation se produit lorsque vous avez un complexe SELECTqui doit créer une table temporaire. Si possible, il utilisera MEMORYet convertira VARCHARen CHARpour la table tmp. Prend maintenant VARCHAR(100)un octet fixe de 100 (ou 300), ce qui peut éventuellement ralentir la requête.
Rick James
@RolandoMySQLDBA, le comportement expliqué dans votre réponse est-il applicable aux formats de ligne Mysql 5.7 DYNAMIC et COMPACT?
Dinesh Kumar
@DineshKumar Ces paragraphes sont toujours dans la documentation 5.7 / 8.0. Veuillez vous référer à dev.mysql.com/doc/refman/5.7/en/innodb-row-format-dynamic.html pour DYNAMIC.
RolandoMySQLDBA
8

Quelle que soit la longueur que vous définissez pour votre colonne varchar, l'espace de stockage utilisé par une colonne vide sera le même.

Les types CHAR et VARCHAR

entrez la description de l'image ici

Cela ne concerne que l'espace utilisé par la colonne varchar et ne prend pas en compte l'espace de stockage total utilisé par la ligne, ses index, ses clés primaires et les autres colonnes.

Comme ypercube le mentionne dans son commentaire, il existe des considérations supplémentaires pour le stockage des lignes dans son ensemble lorsqu'au moins une colonne nullable est présente.

Structure de ligne physique Innodb

La partie de longueur variable de l'en-tête d'enregistrement contient un vecteur de bits pour indiquer les colonnes NULL. S'il y a entre 9 et 15 colonnes qui peuvent être NULL, le vecteur binaire utilise deux octets.)

...

La partie de longueur variable de l'en-tête contient également les longueurs des colonnes de longueur variable. Chaque longueur prend un ou deux octets, selon la longueur maximale de la colonne. Si toutes les colonnes de l'index ne sont PAS NULES et ont une longueur fixe, l'en-tête d'enregistrement n'a pas de partie de longueur variable

Et oui, l'espace de stockage utilisé change en fonction du type que vous choisissez, est-il fixe ou variable, le classement et d'autres facteurs tels que le moteur.

MySQL fait des recommandations sur l'optimisation du stockage des données ici: Optimiser la taille des données

Mise à jour

Une considération supplémentaire avec varchar et c'est la mémoire. Il est important dans MySQL de limiter autant que possible la taille d'une colonne de longueur variable. Même si la colonne est variable et l'espace de stockage utilisé est variable, MySQL allouera de la mémoire en morceaux fixes pour stocker les valeurs. Par exemple, varchar (200) utilisera plus de mémoire que varchar (5). Ce n'est pas un problème d'espace de stockage, mais quelque chose à considérer lors de la définition de vos colonnes.

Craig Efrein
la source
Les nombres ci-dessus supposent CHARACTER SETlatin1 ou ascii. Pour utf8, le stockage requis CHAR(4)est de 12.
Rick James