web-dev-qa-db-fra.com

J'ai besoin de réduire ma base de données - je viens de libérer beaucoup d'espace

Cette question est posée sous différentes formes ici mais la question se résume à:

Je sais que la réduction d'une base de données est risquée. Dans ce cas, j'ai supprimé tellement de données et je ne les utiliserai plus jamais.

  • Comment puis-je réduire ma base de données? Quels fichiers dois-je réduire?
  • Quelles devraient être mes considérations en faisant cela?
  • Dois-je faire quelque chose après?
  • Et si c'est une grande base de données? Puis-je le réduire par petits incréments?
35
Mike Walsh

Quelques mises en garde initiales:

  1. Il est généralement connu comme la pire pratique de jamais réduire une base de données de production ou un fichier de données (les fichiers journaux sont un autre problème comme cette question = parle). Je conseille aux gens de ne pas réduire leurs bases de données dans articles de blog comme celui-ci où je parle de "dimensionnement à droite" et d'une bonne planification. Je ne suis pas seul là-bas ( Paul Randal , Brent Ozar , juste pour fournir quelques liens supplémentaires). Réduire un fichier de données ou des index de fragments de base de données, est lent et laborieux sur vos ressources, peut être un drain sur votre système et n'est qu'une mauvaise chose à faire, généralement
  2. Dans ce cas, nous savons tous que le risque est là, nous sommes prêts à y faire face, mais nous avons libéré beaucoup d'espace que nous savons nous ' Je n'aurai plus jamais besoin de nouveau. Donc, dans ce type spécifique de cas, la réduction a beaucoup de sens comme l'une de nos options.

Si vous avez lu les inquiétudes et les risques et que vous devez encore faire cette réduction parce que vous avez libéré une quantité d'espace significative, j'espère que le reste de cette réponse vous aidera. Mais tenez compte des risques.

Il existe deux approches principales que deux considèrent ici:

1.) Rétrécir Oui, faire le rétrécissement réel - Pensez à utiliser DBCC SHRINKFILE au lieu de DBCC SHRINKDATABASE, vous avez plus de contrôle sur ce qui se rétrécit et comment. Cela entraînera une certaine dégradation des performances à coup sûr - c'est une grande opération qui fait beaucoup d'E/S. Vous pouvez potentiellement s'en tirer avec des rétrécissements répétés à une taille cible qui devient progressivement plus petite.

Il s'agit de l'exemple "A.)" ci-dessus DBCC SHRINKFILE link .. Un fichier de données est réduit à une taille cible de 7 Mo dans cet exemple. Ce format est un bon moyen de rétrécir de façon répétée si votre fenêtre d'indisponibilité le permet. Je le ferais en testant le développement pour voir à quoi ressemblent les performances et à quel niveau vous pouvez aller d'un incrément et pour déterminer le calendrier attendu de la production. Il s'agit d'une opération en ligne - vous pouvez l'exécuter avec des utilisateurs du système accédant à la base de données en cours de réduction, mais il y aura une dégradation des performances, presque garantie. Surveillez et regardez et voyez ce que vous faites sur le serveur, choisissez une fenêtre d'indisponibilité ou une période d'activité plus légère, idéalement.

USE YourDatabase;
GO
DBCC SHRINKFILE (DataFile1, 7);
GO

Rappelez-vous toujours: - chaque fois que vous réduisez, vous fragmentez vos index et devez faire une reconstruction d'index si vous prévoyez de réduire en morceaux sur une période de temps prolongée . Vous engagez maintenant ce coût à chaque fois si vous ne pouvez pas tout faire dans une seule fenêtre.

2.) Nouvelle base de données - Vous pourriez créer une nouvelle base de données et y migrer des données. Vous devez créer un script pour la base de données vide et toutes ses clés, index, objets, procs, fonctions, etc., puis migrer les données vers celle-ci. Vous pouvez écrire des scripts pour cela ou vous pouvez utiliser un outil comme SQL Data Compare de Red Gate ou d'autres fournisseurs avec des outils similaires. C'est plus de travail de configuration de votre côté, plus de développement et de tests, et selon votre environnement, cela peut également faire exploser votre fenêtre d'indisponibilité, mais une option à considérer.

Quand je suis forcé de réduire une base de données Si tel était mon environnement, je chercherais à laisser une foire/grande quantité d'espace blanc dans le fichier de données, car j'aime être un porc de disque et être prêt à une croissance future/inattendue. Donc, je serais d'accord de redonner de l'espace si nous supprimions la majorité de l'espace, mais je ne ferais jamais confiance à ceux qui disent "mais il ne s'agrandira plus" et laisserait toujours - certains un espace blanc. L'itinéraire que j'irais probablement avec ( soupir) est l'approche de rétrécissement si j'avais des fenêtres d'indisponibilité plus petites et que je ne voulais pas encourir la complexité de créer une base de données vide et de migrer des données vers celle-ci. Donc, je le réduirais un tas de fois de manière incrémentielle (en fonction du nombre de fois que je pensais avoir besoin en fonction de mes tests en dev et de la taille souhaitée. En choisissant progressivement une taille de fichier plus petite), puis en reconstruisant les index .. Et puis je ne dirais jamais à personne que j'ai réduit ma base de données; -)

30
Mike Walsh
  1. Comment puis-je réduire ma base de données? Quels fichiers dois-je réduire?: Vous pouvez réduire les fichiers individuellement par la commande DBCC SHRINKFILE Que vous mentionnez. Cela dépend de votre serveur combien de fichiers se compose votre base de données. Une base de données simple possède un fichier de base de données et un fichier journal des transactions.
  2. Quelles devraient être mes considérations en faisant cela?: le rétrécissement affecte votre fragmentation d'index, voir 3ème point. Notez également que vous ne voulez pas réduire le fichier de base de données à une taille minimale, car dans un environnement réel, il augmentera de toute façon. Je voudrais donc régler la taille (dans votre exemple, vous avez donné 7 mégaoctets) de manière à laisser 10% à 20% d'espace libre dans le fichier de base de données, car il sera de toute façon rempli dans l'environnement de production, et vous pouvez sauver certains cycles d'auto-croissance de cette façon. Le nombre réel doit donc être calculé avec soin. Notez également que la "mise à jour de l'espace volumineux" que vous avez effectuée gonflerait encore plus le fichier journal des transactions que l'espace que vous avez gagné dans le fichier DB. De plus, le gain d'espace réel que vous pouvez ressentir sera inférieur à ce que vous attendez mathématiquement! Disons que vous avez mathématiquement libéré 12 concerts, alors vous ne pourrez peut-être que rétrécir
  3. Dois-je faire quoi que ce soit après?: Comme je l'ai mentionné plus tôt, vous voulez réindexer les index dont la fragmentation a été déformée à la suite des changements de SHRINK. Je n'ai pas suffisamment expérimenté si vous devez faire quelque chose de spécial sur les statistiques de requête.
  4. Que faire s'il s'agit d'une grande base de données? Puis-je la réduire par petits incréments? L'opération SHRINK peut être interrompue à tout moment et vous pouvez continuer plus tard. Je conseillerais de l'exécuter sur une base de données hors ligne si possible. En l'interrompant et en le contournant, il avancerait de la même taille de rétrécissement. Théoriquement, vous pouvez réduire par incréments plus petits en spécifiant une taille cible moins stricte au lieu de 7 mégaoctets, mais je dirais que si vous l'exécutez en production, essayez-le. Comme vous le voyez, la fragmentation de l'index et la croissance possible du journal des transactions posent des problèmes. Je ne reviendrais donc qu'une seule fois.

Nous savons tous qu'il n'est pas conseillé de faire du SHRINK régulièrement de toute façon. J'essaie de laisser de côté tous les avertissements et avertissements que vous connaissez probablement de toute façon. Sauvegardez, et ne faites pas cela à la maison si possible :)

Bonus: dans un environnement de réplication, si vous effectuez cette opération sur la base de données de l'éditeur, cela n'entraînera pas la réduction des bases de données des abonnés (ce qui peut avoir le problème de taille car ce sont des éditions Express).

Enfin, mon script de réindexation:

USE YourDBName

DECLARE @TbName VARCHAR(255)
DECLARE @FullTbName VARCHAR(255)
DECLARE @IxName VARCHAR(255)
DECLARE myCursor CURSOR FOR
    SELECT OBJECT_NAME(dmi.object_id) AS TableName,i.name AS IndexName
    FROM sys.dm_db_index_physical_stats(14, NULL, NULL, NULL , 'LIMITED') dmi
    JOIN  sys.indexes i on dmi.object_id = i.object_id and dmi.index_id = i.index_id
    WHERE avg_fragmentation_in_percent > 30
    ORDER BY avg_fragmentation_in_percent
OPEN myCursor
FETCH NEXT FROM myCursor INTO @TbName, @ixName
WHILE @@FETCH_STATUS = 0
BEGIN
    IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = 'dba' AND TABLE_NAME = @TbName)
BEGIN
        SET @FullTbName = 'dba.' + @TbName
        IF (@ixName IS NULL)
        BEGIN
            PRINT 'Reindexing Table ' + @FullTbName
            DBCC DBREINDEX(@FullTbName, '', 0)
        END
        ELSE
        BEGIN
             PRINT 'Reindexing Table ' + @FullTbName + ', Index ' + @IxName
             DBCC DBREINDEX(@FullTbName, @IxName, 0)
        END
    END
    FETCH NEXT FROM myCursor INTO @TbName, @ixName
END
CLOSE myCursor
DEALLOCATE myCursor

La seule variable dans ce cas est le 14, qui peut être obtenu en émettant select DB_ID('YourDBName'), et le script suppose que vous n'êtes intéressé que par les tables du schéma dba. *.

4
Csaba Toth

Vous avez entendu tous les avertissements concernant la réduction des bases de données et ils sont tous vrais. Il va fragmenter vos index et, en général, gâcher votre base de données et ne devrait pas être fait sur un système de production.

Mais, je le fais généralement chaque semaine lorsque je restaure une sauvegarde sur mon poste de travail en raison de l'espace sur mon disque SSD. Attention, je n'ai pas écrit ce script mais je l'ai trouvé il y a des années. Sur d'autres bases de données [250 Go], j'ai créé un package SSIS qui transférera les tables dont j'ai besoin, puis recréera les index pour cette sensation d'index si fraîche.

DECLARE @DBFileName SYSNAME

DECLARE @TargetFreeMB INT

DECLARE @ShrinkIncrementMB INT

SET @DBFileName = 'Set Name of Database file to shrink'

-- Set Desired file free space in MB after shrink

SET @TargetFreeMB = 500
-- Set Increment to shrink file by in MB
SET @ShrinkIncrementMB = 100

SELECT [FileSizeMB] = convert(NUMERIC(10, 2),
round(a.size / 128., 2)),

[UsedSpaceMB] = convert(NUMERIC(10, 2),

round(fileproperty(a.NAME, 'SpaceUsed') / 128., 2)),

[UnusedSpaceMB] = convert(NUMERIC(10, 2),

round((a.size - fileproperty(a.NAME, 'SpaceUsed')) / 128., 2)),

[DBFileName] = a.NAME

FROM sysfiles a

DECLARE @sql VARCHAR(8000)
DECLARE @SizeMB INT
DECLARE @UsedMB INT

SELECT @SizeMB = size / 128.
FROM sysfiles
WHERE NAME = @DBFileName

SELECT @UsedMB = fileproperty(@DBFileName, 'SpaceUsed') / 128.

SELECT [StartFileSize] = @SizeMB
    ,[StartUsedSpace] = @UsedMB
    ,[DBFileName] = @DBFileName

WHILE @SizeMB > @UsedMB + @TargetFreeMB + @ShrinkIncrementMB

BEGIN
    SET @sql = 'dbcc shrinkfile ( ' + @DBFileName + ', ' + convert(VARCHAR(20), @SizeMB - @ShrinkIncrementMB) + ' ) '

    PRINT 'Start ' + @sql
    PRINT 'at ' + convert(VARCHAR(30), getdate(), 121)

    EXEC (@sql)

    PRINT 'Done ' + @sql
    PRINT 'at ' + convert(VARCHAR(30), getdate(), 121)

    SELECT @SizeMB = size / 128.
    FROM sysfiles
    WHERE NAME = @DBFileName

    SELECT @UsedMB = fileproperty(@DBFileName, 'SpaceUsed') / 128.

    SELECT [FileSize] = @SizeMB
        ,[UsedSpace] = @UsedMB
        ,[DBFileName] = @DBFileName
END

SELECT [EndFileSize] = @SizeMB
    ,[EndUsedSpace] = @UsedMB
    ,[DBFileName] = @DBFileName

SELECT [FileSizeMB] = convert(NUMERIC(10, 2), round(a.size / 128., 2))

    ,[UsedSpaceMB] = convert(NUMERIC(10, 2), round(fileproperty a.NAME, 'SpaceUsed') / 128., 2))

,[UnusedSpaceMB] = convert(NUMERIC(10, 2), round((a.size - fileproperty(a.NAME, 'SpaceUsed')) / 128., 2))

,[DBFileName] = a.NAME

FROM sysfiles a
2
user1207758

Cette citation ci-dessous est directement de Microsoft (s'applique aux versions 2008-2016) et donne des conseils sur si/quand et comment utiliser le DBCC SHRINKFILE commande.

https://msdn.Microsoft.com/en-us/library/ms189493.aspx

Meilleures pratiques

Tenez compte des informations suivantes lorsque vous prévoyez de réduire un fichier:

  • Une opération de réduction est plus efficace après une opération qui crée beaucoup d'espace inutilisé, comme une table tronquée ou une opération de suppression de table.
  • La plupart des bases de données nécessitent de l'espace libre pour les opérations quotidiennes normales. Si vous réduisez une base de données à plusieurs reprises et remarquez que la taille de la base de données augmente à nouveau, cela indique que l'espace qui a été réduit est requis pour les opérations normales. Dans ces cas, la réduction répétée de la base de données est une opération inutile.
  • Une opération de réduction ne préserve pas l'état de fragmentation des index dans la base de données et augmente généralement la fragmentation dans une certaine mesure. C'est une autre raison de ne pas réduire à plusieurs reprises la base de données.
  • Rétrécissez plusieurs fichiers dans la même base de données de manière séquentielle au lieu de simultanément. Les conflits sur les tables système peuvent entraîner des retards dus au blocage.
1
g2server