Pourquoi l'espace de données d'une table peut prendre jusqu'à 4 fois la taille des données brutes?

dba.stackexchange https://dba.stackexchange.com/questions/5455

  •  16-10-2019
  •  | 
  •  

Question

I ai une table avec 490 M lignes et 55 Go d'espace de table, donc environ 167 octets par ligne. Le tableau comporte trois colonnes: une VARCHAR(100), un DATETIME2(0) et un SMALLINT. La durée moyenne du texte dans le champ VARCHAR est d'environ 21,5, de sorte que les données brutes devrait être d'environ 32 octets par ligne. 22 + 2 pour le VARCHAR, 6 pour la DATETIME2, et 2 pour le nombre entier sur 16 bits

Notez que l'espace au-dessus est que, non données indices. J'utilise la valeur indiquée sous Propriétés | stockage | général | espace de données.

Bien sûr, il doit y avoir certains les frais généraux, mais 135 octets par ligne semble beaucoup, surtout pour une grande table. Pourquoi pourrait-il être? Quelqu'un at-il vu les autres multiplicateurs semblables? Quels facteurs peuvent influer sur la quantité d'espace supplémentaire requis?

À titre de comparaison, j'ai essayé de créer une table avec deux champs de INT et 1 M lignes. L'espace de données requise était de 16,4 Mo: 17 octets par ligne, par rapport aux 8 octets de données brutes. Une autre table de test avec un INT et un VARCHAR(100) peuplé avec le même texte que la table réelle utilise 39 octets par ligne (44 K lignes), où j'attendre 28 plus un peu.

Ainsi, la table de production a considérablement plus de frais généraux. Est-ce parce qu'il est plus grand? J'attends la taille des index à peu près N * log (N), mais je ne vois pas pourquoi l'espace requis pour les données réelles pour être non linéaire.

Merci d'avance pour tous les pointeurs!

EDIT:

Tous les champs indiqués sont NOT NULL. La vraie table a un PK ordonné en clusters sur le champ VARCHAR et le champ DATETIME2, dans cet ordre. Pour les deux essais, le premier INT était le (cluster) PK.

S'il importe: la table est un enregistrement des résultats de ping. Les champs sont URL, date de ping / temps et temps d'attente en millisecondes. Les données sont constamment en annexe, et jamais mis à jour, mais les données sont supprimées périodiquement pour réduire à seulement quelques enregistrements par heure et par URL.

EDIT:

Une réponse très intéressante suggère que, pour un index avec beaucoup de lecture et l'écriture, la reconstruction ne peut pas être bénéfique. Dans mon cas, l'espace occupé est une préoccupation, mais si les performances d'écriture est plus importante, on peut être mieux avec des indices veule.

Était-ce utile?

La solution

Après des discussions dans les commentaires sur la question initiale, il apparaît dans ce cas, l'espace perdu est causée par le choix de la clé en cluster, ce qui a conduit à la fragmentation massif.

vaut toujours vérifier l'état de la fragmentation par sys.dm_db_index_physical_stats dans ces situations.

Edit: Suite à la mise à jour dans les commentaires

La densité moyenne de la page (avant la reconstruction de l'index ordonné en clusters) était de 24%, ce qui correspond parfaitement à la question initiale. Les pages ne sont que 1/4 plein, de sorte que la taille totale était 4 fois la taille des données brutes.

Autres conseils

Les structures sur disque ont en tête:

  • tête de ligne
  • null bitmap + pointeur
  • décalages de colonne de longueur variable
  • pointeurs de version de ligne (en option)
  • ...

Prendre 2 x 4 octets colonnes int, vous avez

  • 4 octets de tête de ligne
  • 2 octets pointeur vers bitmap NULL
  • 8 octets pour deux colonnes int
  • 3 octets bitmap NULL

Wow 17 octets!

Vous pouvez même pour votre deuxième table de test qui a plus de frais généraux comme votre original:

  • 2 octets pour le nombre de colonnes de longueur variable
  • 2 octets par colonne de longueur variable

Pourquoi la différence? De plus (je ne vais pas créer un lien vers ces)

  • avez-vous déjà index reconstruit pour les défragmenter?
  • ne supprime pas Régénérer l'espace
  • pages de données fractionne si vous insérez dans le milieu
  • des mises à jour peut provoquer des pointeurs vers l'avant (laisse subsister un écart)
  • dépassement de la ligne
  • supprimé colonne varchar sans reconstruction d'index ou DBCC CLEANTABLE
  • tas ou une table (tas n'a pas d'index ordonné en clusters = dossiers éparpillés sur)
  • niveau d'isolement RCSI (appoint 14 octets par ligne)
  • espaces de fin (SET ANSI_PADDING est activée par défaut) dans varchar. Utilisez DATALENGTH à checl, pas LEN
  • Exécuter sp_spaceused avec @updateusage = 'true'
  • ...

Voir ceci: https://stackoverflow.com / questions / 4614771 / sql-server-2008-how-much-espace-does-ce-occupent / 4614799 # 4614799

  • https://stackoverflow.com/questions/3793022/how-to-come-to-limits-of-8060-bytes-per-row-and-8000-per-varchar-nvarchar-valu / 3793265 # 3793265
  • Demandez aux types de données ont été modifiées au fil du temps? été enlevés ont des colonnes de-longueur variable? Les indices ont été défragmenté souvent, mais jamais reconstruit? Ont beaucoup de lignes été supprimé ou ont beaucoup de colonnes de longueur variable été considérablement mis à jour? Quelques bonnes discussions ici .

    Licencié sous: CC-BY-SA avec attribution
    Non affilié à dba.stackexchange
    scroll top