web-dev-qa-db-fra.com

NULL dans MySQL (Performances et stockage)

Qu'est-ce que null fait exactement en termes de performances et de stockage (espace) dans MySQL?

Par exemple:

TINYINT: 1 octet TINYINT w/NULL 1 octet + stocke en quelque sorte NULL?

68
Steve

Cela dépend du moteur de stockage que vous utilisez.

Au format MyISAM, chaque en-tête de ligne contient un champ binaire avec un bit pour chaque colonne pour coder l'état NULL. Une colonne NULL prend toujours de la place, donc NULL ne réduit pas le stockage. Voir https://dev.mysql.com/doc/internals/en/myisam-introduction.html

Dans InnoDB, chaque colonne a un "décalage de début de champ" dans l'en-tête de ligne, qui est d'un ou deux octets par colonne. Le bit haut dans ce décalage de début de champ est activé si la colonne est NULL. Dans ce cas, la colonne n'a pas du tout besoin d'être stockée. Donc, si vous avez beaucoup de NULL, votre stockage devrait être considérablement réduit. Voir https://dev.mysql.com/doc/internals/en/innodb-field-contents.html

MODIFIER:

Les bits NULL font partie des en-têtes de ligne, vous ne choisissez pas de les ajouter.

La seule façon d'imaginer des NULL améliorant les performances est que dans InnoDB, une page de données peut contenir plus de lignes si les lignes contiennent des NULL. Vos tampons InnoDB peuvent donc être plus efficaces.

Mais je serais très surpris si cela fournissait un avantage de performance significatif dans la pratique. S'inquiéter de l'effet des NULL sur les performances relève de la micro-optimisation. Vous devriez concentrer votre attention ailleurs, dans les zones où vous en avez le plus pour votre argent. Par exemple, ajouter des index bien choisis ou augmenter l'allocation de cache de base de données.

93
Bill Karwin

La réponse de Bill est bonne, mais un peu dépassée. L'utilisation d'un ou deux octets pour stocker NULL s'applique uniquement au format de ligne InnoDB REDUNDANT. Depuis MySQL 5.0.3 InnoDB utilise [~ # ~] format de ligne compact [~ # ~] qui utilise un seul bit pour stocker un NULL (bien sûr un octet est le minimum), donc:

Espace requis pour les valeurs NULL = PLAFOND (N/8) octets où N est le nombre de colonnes NULL dans une ligne.

  • 0 NULLS = 0 octets
  • 1-8 NULLS = 1 octet
  • 9-16 NULLS = 2 octets
  • 17-24 NULLS = 3 octets
  • etc...

Selon le site officiel MySQL sur COMPACT vs REDUNDANT:

Le format de ligne compact réduit l'espace de stockage de ligne d'environ 20% au prix d'une utilisation accrue du processeur pour certaines opérations. Si votre charge de travail est typique et limitée par les taux d'accès au cache et la vitesse du disque, le format compact est susceptible d'être plus rapide.

Avantage d'utiliser NULLS sur des chaînes vides ou des zéros:

  • 1 NULL nécessite 1 octet
  • 1 chaîne vide nécessite 1 octet (en supposant VARCHAR)
  • 1 zéro nécessite 4 octets (en supposant INT)

Vous commencez à voir les économies ici:

  • 8 NULLs nécessitent 1 octet
  • 8 chaînes vides nécessitent 8 octets
  • 8 zéros nécessitent 32 octets

D'un autre côté, je suggère d'utiliser des valeurs NULL sur des chaînes vides ou des zéros, car ils sont plus organisés, portables et nécessitent moins d'espace. Pour améliorer les performances et économiser de l'espace, concentrez-vous sur l'utilisation des types de données, des index et des requêtes appropriés au lieu de trucs étranges.

Plus d'informations sur: https://dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html

31
Arian Acosta

Je serais d'accord avec Bill Karwin, bien que j'ajouterais ces conseils MySQL . Le numéro 11 aborde spécifiquement ceci:

Tout d'abord, demandez-vous s'il y a une différence entre avoir une valeur de chaîne vide et une valeur NULL (pour les champs INT: 0 vs NULL). S'il n'y a aucune raison d'avoir les deux, vous n'avez pas besoin d'un champ NULL. (Saviez-vous qu'Oracle considère NULL et la chaîne vide comme étant identiques?)

Les colonnes NULL nécessitent un espace supplémentaire et peuvent ajouter de la complexité à vos déclarations de comparaison. Évitez-les quand vous le pouvez. Cependant, je comprends que certaines personnes peuvent avoir des raisons très spécifiques d'avoir des valeurs NULL, ce qui n'est pas toujours une mauvaise chose.

D'un autre côté, j'utilise toujours null sur des tables qui n'ont pas des tonnes de lignes, principalement parce que j'aime la logique de dire NOT NULL.

Mise à jour Revisitant cela plus tard, j'ajouterais que personnellement je n'aime pas utiliser 0 au lieu de NULL dans la base de données, et je ne le recommande pas . Cela peut facilement entraîner de nombreux faux positifs dans votre application si vous ne faites pas attention.

6

dev.mysql.com/doc/refman/5.0/en/is-null-optimization.html

MySQL peut effectuer la même optimisation sur col_name IS NULL qu'il peut utiliser pour col_name = constant_value. Par exemple, MySQL peut utiliser des index et des plages pour rechercher NULL avec IS NULL

1
Chu Khanh Van