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
sql-server
clustered-index
Daniel Björk
la source
la source
EXEC sp_spaceused
.ALTER INDEX
dé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?)Réponses:
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:
Maintenant, pour ajouter des lignes dans l'ordre d'index (c'est pourquoi j'ai utilisé des nombres pairs uniquement ci-dessus): Ajouter
11
signifierait 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:À partir de là, l'ajout
13
et17
ne se traduira pas par une scission car il y a actuellement de la place dans les pages pertinentes:mais l'ajout de 03:
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:
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'
FILLFACTOR
option 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
FILLFACTOR
est 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 INDEX
dé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.la source
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_spaceused
ne 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.la source
La
sp_spaceused
procé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.
la source