この質問はさまざまな形式でここに尋ねられますが、質問は次のように要約されます。
データベースの縮小は危険を伴うことを知っています。この場合、大量のデータを削除したため、二度と使用しません。
- データベースを縮小するにはどうすればよいですか?どのファイルを縮小しますか?
- これを行う際の考慮事項は何ですか?
- 後は何をすべきですか?
- 大規模なデータベースの場合はどうなりますか?少しずつ縮小できますか?
この質問はさまざまな形式でここに尋ねられますが、質問は次のように要約されます。
データベースの縮小は危険を伴うことを知っています。この場合、大量のデータを削除したため、二度と使用しません。
回答:
いくつかの最初の警告:
懸念事項とリスクについて読んだ後、かなりのスペースを解放したためにこの縮小を行う必要がある場合は、この回答の残りの部分が役立つことを願っています。しかし、リスクを考慮してください。
ここで考慮すべき2つの主なアプローチがあります。
1.)縮小 はい、実際の縮小を行います -のDBCC SHRINKFILE
代わりに使用することを検討してくださいDBCC SHRINKDATABASE
。縮小する対象と方法をより細かく制御できます。これは確かにパフォーマンスの低下を引き起こします-それは大量のIOを行う大規模な操作です。次第に小さくなるターゲットサイズまで繰り返し縮小することで、潜在的に逃げることができます。
これは、上記のDBCC SHRINKFILE
リンクの「A.)」の例です。この例では、データファイルが7MBのターゲットサイズに縮小されています。この形式は、ダウンタイムウィンドウが許す限り繰り返し縮小するのに適した方法です。開発のテストでこれを行い、パフォーマンスがどのように見えるか、増分をどれだけ低く/高くできるかを確認し、本番で予想されるタイミングを決定します。これはオンライン操作です-縮小されているデータベースにアクセスするシステム内のユーザーで実行できますが、パフォーマンスが低下し、ほぼ保証されます。そのため、理想的には、サーバーに対して行っていることを監視および監視し、ダウンタイムウィンドウまたはより軽いアクティビティの期間を選択します。
USE YourDatabase;
GO
DBCC SHRINKFILE (DataFile1, 7);
GO
常に覚えておいてください: -縮小するたびにインデックスを断片化し、長期間にわたってチャンクで縮小する場合はインデックスの再構築を行う必要があります。1つのウィンドウですべてを完了できない場合、毎回そのコストが発生します。
2.)新しいデータベース - 新しいデータベースを作成して、そこにデータを移行できます。空のデータベースとそのすべてのキー、インデックス、オブジェクト、プロシージャ、関数などのスクリプトを作成し、データをそこに移行する必要があります。このためのスクリプトを作成することも、Red GateのSQL Data Compareなどのツールまたは同様のツールを持つ他のベンダーを使用することもできます。これはあなたの側でのより多くのセットアップ作業であり、より多くの開発とテストであり、あなたの環境によってはダウンタイムウィンドウを吹き飛ばすかもしれませんが、考慮すべきオプションです。
私はときに強制していますデータベースを縮小するために 、これは私の環境であれば、私はので、私のディスクを独り占めいるようと将来/予想外の成長のために準備されたいデータファイル内の空白の公正/多額の金額を残すように見えると思います。私たちは宇宙の大部分を削除した場合、私は大丈夫寄付スペースバックだろうが、私はそれらが言って「それは再び成長することはありません」と、まだ残して信用したことがなかったので、いくつかの空白を。たぶん行くルート(ため息)は、ダウンタイムウィンドウが小さく、空のDBを作成してそこにデータを移行するという複雑さを避けたい場合の縮小アプローチです。(私は私のdevにテストと希望のサイズに基づいてする必要がありました。徐々に小さいファイルサイズを選択すると思った回数に基づいて)漸増それを倍の束を縮小して、インデックスを再構築...う、私はそう「そして私d誰にも私がデータベースを縮小したとは決して言わない;-)
DBCC SHRINKFILE
言及したコマンドでファイルを個別に縮小できます。データベースのファイル数はサーバーに依存します。単純なデータベースには、1つのデータベースファイルと1つのトランザクションログファイルがあります。とにかく定期的にSHRINKを行うことはお勧めできません。とにかくあなたがおそらく知っているすべての警告と免責事項を除外しようとします。バックアップし、可能であれば自宅でこれをしないでください:)
ボーナス:レプリケーション環境では、パブリッシャーデータベースでこれを実行しても、サブスクライバーデータベースが縮小することはありません(Expressエディションであるため、サイズに問題がある可能性があります)。
最後に、インデックス再作成スクリプト:
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
この唯一の変数は14です。これはselectを発行することで取得できDB_ID('YourDBName')
、スクリプトはdba。*スキーマのテーブルのみに関心があると想定しています。
データベースの縮小に関するすべての警告を聞いたことがありますが、それらはすべて真実です。これはインデックスを断片化しますが、一般的にはデータベースを破壊するため、本番システムでは実行しないでください。
しかし、私は通常、SSDドライブのスペースが原因でワークステーションにバックアップを復元するときに、週単位でこれを行います。念のため、このスクリプトは書いていませんが、数年前に発見しました。他のデータベース[250 GB]で、必要なテーブルを転送するSSISパッケージを作成し、そのためにインデックスを再作成します。
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
以下のこの引用は、Microsoftから直接のものであり(バージョン2008-2016に適用)、DBCC SHRINKFILE
コマンドを使用する場合/いつ、どのように使用するかについてのガイダンスを提供します。
https://msdn.microsoft.com/en-us/library/ms189493.aspx
ベストプラクティス
ファイルを圧縮する場合は、次の情報を考慮してください。
- 縮小操作は、テーブルの切り捨て操作やテーブルの削除操作など、多くの未使用領域を作成する操作の後に最も効果的です。
- ほとんどのデータベースでは、通常の日常業務に使用できる空き領域が必要です。データベースを繰り返し縮小し、データベースサイズが再び大きくなることに気付いた場合、これは通常の操作に縮小されたスペースが必要であることを示しています。これらの場合、データベースを繰り返し縮小することは無駄な操作です。
- 縮小操作では、データベース内のインデックスの断片化状態が保持されず、一般的にある程度断片化が増加します。これは、データベースを繰り返し圧縮しないもう1つの理由です。
- 同じデータベース内の複数のファイルを同時にではなく順次に圧縮します。システムテーブルでの競合は、ブロッキングによる遅延を引き起こす可能性があります。