Les colonnes vides occupent-elles de l'espace dans une table?

20

J'ai une table qui contient des informations très basiques. Juste un titre et quelques champs de date. Il y a un champ appelé commentaires qui est varchar (4000) La plupart du temps, nous le laissons vide, mais parfois nous entrons une grande quantité de données ici. Est-ce vraiment une mauvaise conception? Ou est-ce juste légèrement inefficace?

Je suppose que la création d'un tableau séparé pour cette colonne serait préférable.

Remarque: il s'agit du serveur SQL 2008

entrez la description de l'image ici

aron
la source
Merci à tous pour vos retours! J'ai décidé de rester simple et de conserver la colonne dans le tableau et de ne pas la placer dans un autre tableau. Cependant, j'ai utilisé la fonctionnalité SPARSE dans SQL 2008 afin que le champ n'utilise aucun espace.
2
Juste curieux, qu'est-ce que "la plupart du temps"? Combien de lignes au total et quel pourcentage a une valeur ici? Je me demande simplement si vous prévoyez de faire des comparaisons espace / performances en utilisant SPARSEet en n'utilisant pas SPARSE...
Aaron Bertrand

Réponses:

9

Pour des performances plus prévisibles (et pour éviter d'avoir une variation élevée des lignes par page), je préférerais stocker ces données dans une table associée - surtout si elles ne sont remplies qu'un petit pourcentage du temps, et surtout si elles ne sont récupérées que dans certaines des requêtes. Les lignes où se trouve cette valeur NULLcontribuent à la surcharge d'espace, mais cela est minime. Plus important sera de savoir comment une page ne peut contenir que deux lignes et la page suivante peut contenir 500 lignes - cela peut vraiment avoir un impact sur les statistiques et vous feriez mieux de diviser cela afin qu'il soit stocké séparément et n'impacte pas toutes vos opérations sur la table de base.

Aaron Bertrand
la source
12

Il prend un minimum d'espace lorsqu'il n'est pas utilisé

  • un bit dans le bitmap NULL
  • deux octets pour la longueur (qui sera zéro lorsque NULL)

Les frais généraux sont minimes et l'optimisation sera prématurée.

Jusqu'à ce que vous sachiez que vous avez un problème, conservez-le dans une seule table. Vous brisez KISS en introduisant des jointures externes et en ajoutant une surcharge lors de l'interrogation des données.

Voir /programming/3793022/how-to-come-to-limits-of-8060-bytes-per-row-and-8000-per-varchar-nvarchar-valu/3793265#3793265 pour plus

gbn
la source
10

Je pense qu'un tableau séparé serait préférable pour améliorer la densité des pages et réduire la fragmentation, surtout si vous ne remplissez pas toujours ce champ.

  • Une page de données contient environ 8000 octets
  • Vous avez quelques lignes avec disons 100 octets et quelques lignes avec plus de 4000 octets
  • Ces longues lignes seront sur une page par elles-mêmes, et le reste de la page est un espace "gaspillé" que votre base de données occupe mais ne contiendra probablement jamais de données
  • Si vous ajoutez des données à ce long champ pour un enregistrement sur une page presque pleine, cela dépassera probablement la page et entraînera un pointeur vers la page avec le reste de l'enregistrement

Toutes ces pages vides et pointeurs conduisent à de mauvaises performances. Normalisez ce champ si vous le pouvez.

JNK
la source
4

Cette question semble très similaire: les colonnes vides supplémentaires affectent-elles la taille de la table SQL de manière significative?

Il semble que la réponse soit oui, cela prend de la place, mais il existe un algorithme de compression pour les colonnes avec beaucoup de valeurs nulles.

En ce qui concerne le design, je pense qu'avoir une table externe liée à cela serait un design plus propre. Avoir une colonne avec des valeurs nulles fréquentes rend plus difficile pour les utilisateurs de la base de données car ils pourraient accidentellement utiliser une valeur nulle s'ils ne font pas attention. Par conséquent, le code utilisant la base de données devrait contenir une vérification des erreurs et il devient simplement laid à partir de là.

Communauté
la source
2
Pour être explicite, l'algorithme de compression ne s'applique qu'aux colonnes explicitement définies comme SPARSE, et pas seulement aux «colonnes avec beaucoup de valeurs nulles».
Aaron Bertrand
2

Tout ira bien - c'est déjà une colonne varchar, donc elle n'utilise de l'espace que lorsqu'elle contient des données. Si vous aviez beaucoup de colonnes de taille fixe nullable comme int, vous pourriez avoir des problèmes d'utilisation de l'espace.

En ce qui concerne le mettre dans une autre table, je ne me dérangerais pas. Vous pouvez également envisager d'utiliser varchar (max) et les options d'entrée / sortie de ligne. Encore une fois, probablement prématuré.

Cade Roux
la source
1
L'optimisation prématurée peut souvent être un vrai problème, mais cela dépend du coût de refactoring ultérieur. Si vous savez aujourd'hui que seulement 1% de vos lignes contiendront des données dans cette colonne et que vous vous attendez à ce que le tableau s'agrandisse au fil du temps, quelle est la valeur de la persistance de ces données dans le tableau actuel pour n'en subir les conséquences que lorsque vous évoluez? Je suis tout à fait d'accord pour éviter une optimisation prématurée, mais il y a un moment où j'évalue l'effet à long terme de le faire.
Aaron Bertrand
@Aaron Bertrand est d'accord. Les gens posent des questions sur les performances ici et il est facile de supposer qu'ils peuvent avoir une application qui se compose de millions de lignes et qu'ils doivent utiliser toutes les armes de la boîte à outils et garder tout cela à l'esprit. D'un autre côté, l'utilisateur semble parfois être au début d'une courbe d'apprentissage et il est difficile de lui demander de consacrer du temps à quelque chose qui devrait probablement être inférieur à ses priorités. En outre, avec varchar (max), vous pouvez effectivement appuyer sur un commutateur pour commencer à stocker hors ligne. Je pense que la vraie réponse ici est "Vous ne nous avez pas vraiment donné suffisamment d'informations pour donner une réponse définitive".
Cade Roux