reconstruire sur un index clusterisé, pourquoi la taille des données diminue-t-elle?

10

Lorsque nous avons effectué une reconstruction sur un index clusterisé sur une table contenant environ 15 Go de données et que la taille des données a été réduite à 5 Go, comment cela peut-il être? Quel type de "données" est supprimé?

Taille des données, je veux dire la colonne "données" de DBCC sp_spaceused

Avant de reconstruire sur un index clusterisé:

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    39169656 KB 15857960 KB 22916496 KB 395200 KB

Après la reconstruction sur un index clusterisé:

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    29076736 KB 5867048 KB  22880144 KB 329544 KB

TSQL pour la reconstruction:

USE [DAX5TEST]
GO
ALTER INDEX [I_212RECID] ON [dbo].[LEDGERJOURNALTRANS] REBUILD PARTITION = ALL WITH ( PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, ONLINE = ON, SORT_IN_TEMPDB = OFF, DATA_COMPRESSION = PAGE, FILLFACTOR = 85 )
GO
Daniel Björk
la source
Déterminez-vous la taille des données à partir de la taille du fichier?
JNK
Taille des données je veux dire la colonne "data" de DBCC sp_spaceused
Daniel Björk
Ce serait la colonne "données" de EXEC sp_spaceused.
RLF
1
Est-ce que tout le monde a manqué que OP utilise la compression de page = activé dans son script de reconstruction et je suppose que ce n'était pas le cas auparavant. Daniel pouvez-vous confirmer?
Shanky
1
@Shanky: Cette ALTER INDEXdéclaration semble avoir été générée par du code (car elle inclut un tas d'options dans leur paramètre par défaut), donc je soupçonne qu'elle a été construite à partir des options existantes de l'index. Mais vous avez raison: si la compression n'était pas activée sur l'index cluster avant qu'elle ne soit exécutée, cela expliquerait certainement la majeure partie de la réduction de l'empreinte des données. (encore une fois: Daniel, pourriez-vous confirmer dans un sens ou dans l'autre?)
David Spillett

Réponses:

16

Lorsqu'une table a un index clusterisé, l'index est les données de la table (sinon vous avez une table de type segment de mémoire). Une reconstruction de l'index clusterisé (n'importe quel index en fait, mais l'espace ne serait pas compté comme "données" pour un index non clusterisé) entraînera la fusion des pages partiellement utilisées dans une forme plus complète.

Au fur et à mesure que vous insérez des données dans un index (en cluster ou autre) dans l'ordre des feuilles d'index, les pages sont créées selon les besoins et vous n'aurez qu'une seule page partielle: celle à la fin. Lorsque vous saisissez des données dans l'ordre d'index, une page doit être divisée pour que les données tiennent au bon endroit: vous vous retrouvez avec deux pages qui sont environ à moitié pleines et la nouvelle ligne va dans l'une d'entre elles. Au fil du temps, cela peut se produire beaucoup, consommant une bonne quantité d'espace supplémentaire, bien que dans une certaine mesure, les insertions futures combleront certaines lacunes. Les pages non-feuilles verront également un effet similaire, mais les pages de données réelles sont beaucoup plus importantes qu'elles ne le sont.

Les suppressions peuvent également entraîner des pages partielles. Si vous supprimez toutes les lignes d'une page, elles sont comptées comme «inutilisées» mais s'il reste une ou plusieurs lignes de données, elles sont toujours comptées comme étant utilisées. Même s'il n'y a qu'une seule ligne utilisant 10 octets dans une page, cette page compte comme 8192 octets dans le nombre d'espace utilisé. Encore une fois, les insertions futures pourraient combler une partie de l'écart.

Pour les lignes de longueur variable, les mises à jour peuvent également avoir le même effet: lorsqu'une ligne devient plus petite, elle peut laisser de l'espace dans sa page qui n'est pas facile à réutiliser plus tard, et si une ligne dans une page presque pleine s'allonge, elle pourrait forcer un fractionnement de page .

SQL Server ne passe pas de temps à essayer de normaliser les données en réorganisant la façon dont les pages sont utilisées, jusqu'à ce que cela soit explicitement indiqué à votre ordre de reconstruction d'index, car de tels exercices de récupération de place pourraient être un cauchemar pour les performances.

Je soupçonne que c'est ce que vous voyez, bien que je dirais qu'avoir suffisamment d'espace alloué pour environ 2,7 fois la quantité dont les données ont absolument besoin est un cas particulièrement mauvais. Cela peut impliquer que vous avez quelque chose de aléatoire comme l'une des clés significatives de l'index (une colonne UUID peut-être), ce qui signifie qu'il est peu probable que de nouvelles lignes soient ajoutées dans l'ordre d'index, et / ou qu'un nombre important de suppressions se soient produites récemment.

Exemple de fractionnement de page

Insertion par ordre d'index avec des lignes de longueur fixe dont quatre s'insèrent dans une page:

Start with one empty page: 
        [__|__|__|__]
Add the first item in index order:
        [00|__|__|__]
Add the next three
        [00|02|04|06]
Adding the next will result in a new page:
        [00|02|04|06] [08|__|__|__]
And so on...
        [00|02|04|06] [08|10|12|14] [16|18|__|__]

Maintenant, pour ajouter des lignes dans l'ordre d'index (c'est pourquoi j'ai utilisé des nombres pairs uniquement ci-dessus): Ajouter 11signifierait soit étendre cette deuxième page (pas possible car elles sont de taille fixe), déplacer tout ce qui est supérieur à 11 vers le haut (beaucoup trop cher sur un grand index) ou fractionner la page comme ceci:

[00|02|04|06] [08|10|11|__] [12|14|__|__] [16|18|__|__]

À partir de là, l'ajout 13et 17ne se traduira pas par une scission car il y a actuellement de la place dans les pages pertinentes:

[00|02|04|06] [08|10|11|__] [12|13|14|__] [16|17|18|__]

mais l'ajout de 03:

[00|02|03|__] [04|06|__|__] [08|10|11|__] [12|13|14|__] [16|17|18|__]

Comme vous pouvez le voir, après ces opérations d'insertion, nous avons actuellement 5 pages de données allouées qui pourraient contenir un total de 20 lignes, mais nous n'en avons que 14 ("gaspillant" 30% de l'espace).

Une reconstruction avec des options par défaut (voir ci-dessous à propos du "facteur de remplissage") entraînerait:

[00|02|03|04] [06|08|10|11] [12|13|14|16] [17|18|__|__]

enregistrer une page dans cet exemple simple. Il est facile de voir comment les suppressions peuvent avoir un effet similaire à celui des insertions hors index.

Atténuation

Si vous vous attendez à ce que les données viennent dans un ordre assez aléatoire par rapport à l'ordre des index, vous pouvez utiliser l' FILLFACTORoption lors de la création ou de la reconstruction d'un index pour dire à SQL Server de laisser artificiellement des lacunes à combler ultérieurement - réduisant les fractionnements de page à long terme mais prendre plus de place au départ. Bien sûr, obtenir cette valeur erronée peut aggraver les choses plutôt que d'améliorer la situation, alors manipulez-les avec soin.

Le fractionnement de page, en particulier sur l'index cluster, peut avoir une incidence sur les performances pour les insertions / mises à jour.Il FILLFACTORest donc parfois modifié pour cette raison au lieu du problème d'utilisation de l'espace dans les bases de données qui voient beaucoup d'activité d'écriture (mais pour la plupart des applications, où les lectures l'emportent sur les écritures de plusieurs ordres de grandeur, il est généralement préférable de laisser le facteur de remplissage à 100%, sauf dans des cas spécifiques comme lorsque vous avez des index sur des colonnes avec un contenu effectivement aléatoire).

Je suppose que d'autres bases de données de grands noms ont une option similaire, si vous avez également besoin de ce niveau de contrôle.

Mettre à jour

En ce qui concerne la ALTER INDEXdéclaration ajoutée à la question après avoir commencé à taper ce qui précède: je suppose que les options sont les mêmes que lorsque l'index a été créé (ou reconstruit pour la première fois) mais sinon, l'option de compression pourrait être très importante si elle était ajoutée temps. Dans cette déclaration également, le facteur de remplissage est défini sur 85% et non sur 100%, de sorte que chaque page feuille sera vide à ~ 15% immédiatement après la reconstruction.

David Spillett
la source
2
+1 Si le facteur de remplissage de page est inférieur à 100%, par exemple si le facteur de remplissage de page était de 50%, l'index cluster nouvellement reconstruit (le tableau ) serait deux fois plus grand que s'il était reconstruit avec un facteur de remplissage de 100%.
Max Vernon
6

Lorsque vous reconstruisez un index, il place littéralement toutes les données sur de nouvelles pages. Ce que je soupçonne, c'est que vous avez supprimé beaucoup de données avant la reconstruction, par exemple supprimé une colonne, mis à jour une colonne à largeur variable pour avoir moins de données, changé une taille de colonne à largeur fixe ou supprimé beaucoup de lignes. L'une ou l'autre de ces opérations pourrait laisser beaucoup d'espace vide sur les pages, qui ne seraient pas récupérées avant la reconstruction. La colonne "données" dans sp_spaceusedne mesure pas les données réelles, mais le nombre de pages 8K utilisées pour stocker les données. Ces pages sont désormais plus pleines en raison de la reconstruction, de sorte que la même quantité de données s'adapte sur un plus petit nombre de pages.

Aaron Bertrand
la source
5

La sp_spaceusedprocédure stockée n'examine pas la taille totale culmulative des lignes de la base de données. Il indique la taille de l'espace alloué pour contenir ces données dans la taille cumulée des extensions allouées pour les données.

Si un espace libre important est disponible, par exemple à partir de nombreuses lignes supprimées, une reconstruction de l'index clusterisé compacterait l'espace en pages et étendues pour être plus efficace (c'est-à-dire plus petit) pour des raisons de performances.

Ainsi, aucune donnée n'aurait dû être supprimée, mais le processus de reconstruction a rendu l'espace libre qui était incorporé dans les pages de données à nouveau disponible.

RLF
la source