La meilleure façon de réduire une base de données après avoir annulé les données de varbinary (max)?


8

Nous avons une base de données avec une grande quantité de données stockées dans un champ de type varbinary (max) . À un moment donné, nous pouvons purger ces données pour la plupart des lignes, mais pas toutes. Notre plan est de rendre ce champ annulable et de simplement annuler les données lorsqu'elles ne sont plus nécessaires. Une fois cela fait, nous aimerions réduire la taille de la base de données. Quelle est la meilleure façon d'y parvenir?

S'il n'y a pas un bon moyen de récupérer de l'espace avec la configuration actuelle, une idée que j'ai est de déplacer ce champ de données vers une table séparée avec seulement deux colonnes: la clé de la table principale et le champ de données. Ensuite, nous pourrions simplement supprimer les lignes lorsqu'elles ne sont plus nécessaires. (Et puis faites une sorte de rétrécissement.) Cependant, ce serait un changement beaucoup plus difficile à faire que de simplement rendre le champ existant annulable.

Remarque: En fait, je ne me soucie pas tellement de réduire la taille du fichier de base de données, mais je me soucie que l'espace nouvellement libéré devienne réutilisable.

Plus de 90% de la taille de la base de données est ce seul champ. Je suis déjà à 3 To.

Réponses:


13

Il me semble que simplement mettre à jour les colonnes pour NULLlibérer des pages à réutiliser. Voici une démo Very Scottish®, pour célébrer qu'il est presque 17h, HNE.

USE tempdb;

DROP TABLE IF EXISTS dbo.RobertBurns;

CREATE TABLE dbo.RobertBurns
(
    Id INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
    Scotch VARCHAR(50),
    HaggisAddress VARBINARY(MAX)
);

DECLARE @AddressToAVarbinaryHaggis VARBINARY(MAX); 
DECLARE @AddressToAHaggis NVARCHAR(MAX) = N'
Good luck to you and your honest, plump face,
Great chieftain of the pudding race!
Above them all you take your place,
        gut, stomach-lining, or intestine,
You''re well worth a grace
        as long as my arm.

The overloaded serving tray there you fill,
Your buttocks shaped like a distant hilltop,
Your wooden skewer could be used to fix a mill
         if need be,
While through your pores your juices drip
         like liquid gold.

His knife see the serving-man clean,
And then cut you up with great skill,
Making a trench in your bright, gushing guts
        To form a ditch,
And then, 0h! What a glorious sight!
        Warm, steaming, and rich!

Then, spoonful after spoonful, they eagerly eat,
The devil will get the last bit, on they go,
Until all their well-stretched stomachs, by-and-by,
        are bent like drums,
Then the head of the family, about to burst,
        murmurs “Thank the Lord".

Is there a pretentious soul who, over his French ragout,
Or Italian cuisine that would make a pig sick,
Or French stew that would make that same pig ill
        with complete and utter disgust,
Looks down with a sneering, scornful attitude,
        on such a meal? (as Haggis)

Poor devil! See him over his trash!
As feeble as a withered bullrush,
His skinny leg no thicker than a thin rope,
        His fist the size of a nut,
Through a river or field to travel,
        Completely unfit!

But look at the healthy, Haggis-fed person!
The trembling earth respects him as a man!
Put a knife in his fist,
        He''ll make it work!
And legs, and arms, and heads will come off,
        Like the tops of thistle.

You Powers who look after mankind,
And dish out his bill of fare,
Old Scotland wants no watery, wimpy stuff
        That splashes about in little wooden bowls!
But, if You will grant her a grateful prayer,
        Give her a Haggis!';


INSERT dbo.RobertBurns (Scotch, HaggisAddress )
SELECT TOP 1000 
CASE WHEN x.c % 15 = 0 THEN 'Laphroaig'
     WHEN x.c % 5 = 0 THEN 'Lagavulin'
     WHEN x.c % 3 = 0 THEN 'Port Ellen'
     ELSE 'Ardbeg'
END AS Scotch, 
CONVERT(VARBINARY(MAX), REPLICATE(@AddressToAHaggis, x.c % 20 + 1))
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY @@ROWCOUNT) AS c
FROM sys.messages AS m
) AS x;

CREATE INDEX ix_novarbinary ON  dbo.RobertBurns (Scotch, Id);
CREATE INDEX ix_yesvarbinary ON dbo.RobertBurns (Scotch, Id) INCLUDE (HaggisAddress);

Avec des lignes insérées, vérifions sur nos pages d'index.

SELECT   OBJECT_NAME(i.object_id) AS table_name,
         i.name AS index_name,
         MAX(a.used_pages) AS leaf_me_alone
FROM     sys.indexes AS i
JOIN     sys.partitions AS p
ON p.object_id = i.object_id
   AND p.index_id = i.index_id
JOIN     sys.allocation_units AS a
ON a.container_id = p.partition_id
WHERE OBJECT_NAME(i.object_id) = 'RobertBurns'
GROUP BY i.object_id, i.index_id, i.name
ORDER BY OBJECT_NAME(i.object_id), i.index_id;

Après l'insert, je reçois ceci. Les pages réelles peuvent varier pour vous.

table_name  index_name                      leaf_me_alone
RobertBurns PK__RobertBu__3214EC074BE633A2  5587
RobertBurns ix_novarbinary                  10
RobertBurns ix_yesvarbinary                 5581

Sortons NULLquelques rangées!

UPDATE rb
    SET rb.HaggisAddress = NULL
FROM dbo.RobertBurns AS rb
WHERE rb.Id % 15 = 0;

Et revenez sur nos pages:

table_name  index_name                      leaf_me_alone
RobertBurns PK__RobertBu__3214EC074BE633A2  5300
RobertBurns ix_novarbinary                  10
RobertBurns ix_yesvarbinary                 5273

Le nombre de pages a donc été réduit. Huzzah! Pour les deux index qui touchent nos VARBINARYdonnées, ils ont perdu une page buncha. Cela signifie qu'ils sont de retour en circulation pour d'autres objets à utiliser. Puisque je suis dans tempdb, ils sont probablement engloutis assez rapidement par toutes les ordures qui se passent ici.

Maintenant, remettons quelques données:

INSERT dbo.RobertBurns (Scotch, HaggisAddress )
SELECT TOP 10 rb.Scotch, rb.HaggisAddress
FROM dbo.RobertBurns AS rb;

Et de retour:

table_name  index_name                      leaf_me_alone
RobertBurns PK__RobertBu__3214EC074BE633A2  5330
RobertBurns ix_novarbinary                  11
RobertBurns ix_yesvarbinary                 5305

Le nombre de pages a légèrement augmenté.

Il semble donc que vous n'ayez rien à faire de trop fou, ou même que vous réduisiez votre base de données pour obtenir une réutilisation de l'espace. Je pense que vous confondiez le comportement de la suppression de colonnes et DBCC CLEANTABLEque vous deviez exécuter ce que vous faites réellement.

J'espère que cela t'aides!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.