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 cette donnée pour la plupart des lignes, mais pas toutes. Notre plan consiste à faire valoir ce champ nullable et simplement nulle des données lorsqu'elle n'est plus nécessaire. Une fois que nous ferons que nous aimerions réduire la taille de la DB. Quelle est la meilleure façon d'y parvenir?
S'il n'y a pas de bon moyen de récupérer l'espace avec la configuration actuelle, une idée que j'ai consiste à déplacer ce champ de données à une table séparée avec seulement deux colonnes: la clé de la table principale et du champ de données. Ensuite, nous pourrions simplement supprimer les lignes quand ils ne sont plus nécessaires. (Et ensuite faire une sorte de rétrécissement.) Cependant, cela serait un changement beaucoup plus difficile à faire que de simplifier le champ existant nullable.
Remarque: Je me soucie effectivement de rendre le fichier de base de données plus petit, mais je me soucie de l'espace nouvellement libéré de devenir réutilisable.
Plus de 90% de la taille de la DB est celui-ci. Je suis déjà à 3 ToB.
Cela me semble que simplement mettre à jour les colonnes à NULL
_ libérera des pages de réutilisation. Voici une démo très scottish®, pour le célébrer presque 17h00, est.
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 cela. 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
Soyons NULL
_ Sortir des lignes!
UPDATE rb
SET rb.HaggisAddress = NULL
FROM dbo.RobertBurns AS rb
WHERE rb.Id % 15 = 0;
Et revenez dans nos pages:
table_name index_name leaf_me_alone
RobertBurns PK__RobertBu__3214EC074BE633A2 5300
RobertBurns ix_novarbinary 10
RobertBurns ix_yesvarbinary 5273
Donc, le nombre de pages a été réduit. Huzzah! Pour les deux index qui touchent nos données VARBINARY
, ils ont perdu des pages de buncha. Cela signifie qu'ils sont de retour en circulation pour d'autres objets à utiliser. Depuis que je suis dans Tempdb, ils sont probablement gobillés assez rapidement par toutes les ordures qui vont ici.
Maintenant, mettons des données dans:
INSERT dbo.RobertBurns (Scotch, HaggisAddress )
SELECT TOP 10 rb.Scotch, rb.HaggisAddress
FROM dbo.RobertBurns AS rb;
Et vérifier dans:
table_name index_name leaf_me_alone
RobertBurns PK__RobertBu__3214EC074BE633A2 5330
RobertBurns ix_novarbinary 11
RobertBurns ix_yesvarbinary 5305
Les comptes de page ont un peu augmenté.
Ainsi, on dirait que vous n'êtes pas obligé de faire quelque chose de trop fou, ni même de réduire votre base de données pour obtenir une réutilisation de l'espace. Je pense que vous vous confondez le comportement des colonnes abandonnées et que vous avez besoin de courir DBCC CLEANTABLE
Avec ce que vous faites réellement.
J'espère que cela t'aides!