web-dev-qa-db-ja.com

SQL Serverデータベースが縮小しない

未使用のスペースがたくさんあるSQLデータベースがあります。ただし、タスクを実行すると|縮小|データベースとタスク|縮小| Management Studioからのファイルは、領域を解放していません。
残念ながら、それが実行されているマシンは、ハードディスク領域が不足しています。このスペースが解放されない理由に関するアイデア。

また、DBのリカバリモードはシンプルに設定されています。 enter image description here

ファイルを圧縮するときに表示される未使用のダイアログは次のとおりです。 enter image description here

T-SQLでもこれを試してみました

DBCC SHRINKDATABASE(myDatabase、5);

私は次の応答を受け取ります:

DBCC SHRINKDATABASE:データベースID 6のファイルID 1は、再利用するのに十分な空き領域がないためスキップされました。 DBCC SHRINKDATABASE:データベースID 6のファイルID 2は、再利用するのに十分な空き領域がないためスキップされました。 DBCCの実行が完了しました。 DBCCがエラーメッセージを出力した場合は、システム管理者に連絡してください。

18
DermFrench

私は乱暴な推測をして、データベースが完全復旧を使用するように設定されていると言います。上記の画像に基づいてログを完全にバックアップしたことはありません。これが事実である場合、ログファイルはどんどん大きくなっており、バックアップを取っていないために消去できません。

部屋に完全なバックアップがある場合は、ログのバックアップを取り、再度圧縮を試みます。正常に動作するはずです。

最悪の場合(特に、これが本番データベースの場合は、最悪の場合を意味します)は、データベースをSIMPLEリカバリに設定し、縮小してからバックアップを取得します。これは、通常の縮小のための十分なスペースがない場合でも機能します。

この時点で、データベースの定期的なバックアップを設定してください。

詳細は here を参照してください。


編集:

ログとデータファイルの空き容量の割合を教えてください。また、sys.databasesのlog_reuse_wait_descを確認することもできます。

SELECT name, log_reuse_wait_desc FROM sys.databases 

そして最後に、確かに重要なこととして、縮小のTRUNCATEONLYオプションを試しましたか?

DBCC SHRINKFILE (Adventureworks2008R2_Log, TRUNCATEONLY)
6
Kenneth Fisher

ディスク領域を取得するには、ファイルを圧縮する必要もあります。縮小| SQL Server Management Studioのファイル

データベースの予想される成長に応じて、オプション「未使用スペースを解放する前にファイルを再編成する」をチェックし、空きスペースの割合を設定する必要があります。

5
Rom Eh

これには多くの理由があります。考えられるすべての理由を述べ、その後、問題を解決するための解決策を定義します。

  1. DBCCの出力にあるように、データベースファイルを圧縮するのに十分なディスク容量がありません。言い換えると。データベースファイルから新しく作成されたファイルにページを移動しようとしました。この間、ページは2回存在します。その後、SQL Serverは古いデータベースファイルを削除し、新しく作成されたファイルを本番用に使用します。ディスク容量を増やすか、下記の解決策に従う必要がある場合があります。
  2. 縮小を防ぐもう1つのポイントは、データベースロック(これはあなたのケースではありません)かもしれません。 DDLの変更中にデータベースがロックされている場合、データベースファイルを圧縮できません。ウィザードでファイルを圧縮すると、たまにタイムアウトメッセージが表示されることがあります。スクリプトとして実行する場合、通常はロックが解除されるまで待機してからファイルを圧縮します。

考えられる解決策

最も簡単な解決策は計画です!データベースを確認し、1日に挿入されるデータの量を評価して、成長率を判断してください。デフォルトでは、SQL Serverはファイルを10%増やします。 100MBしか保持していないデータベースの場合、これは10MBになるので悪くありません。しかし、データベースがどんどん大きくなると、成長に多くのリソースと時間がかかります(100GB-> 10 GB、1TB-> 100GBなど)。成長係数をMBで定義します。大きなトランザクションでディスクに負荷がかかり、操作が遅くなるため、小さすぎないようにしてください(1 MBなど)。ただし、大きすぎて巨大な書き込み操作(10 GBなど)を引き起こすことはできません。

さらに、エスカレートする可能性のあるデータベース(ロギングデータベースなど)の拡張制限を定義します。制限に達した場合、トランザクションは失敗する可能性がありますが、データベースのログ記録に大きな影響はありません。ただし、ロギングデータベースが使用可能なディスク領域をすべて使い果たすと、本番データベースでトランザクションが中止またはロールバックする可能性があります。

問題がある場合、ディスク容量が小さすぎて、使用済みのディスク容量を再び保持することができません(たとえば:140GBファイル、40GB空き、再編成には100GBを意味します->には最低100GBの追加空き容量が必要です移動操作での縮小時)、TRUNCATEONLYフラグを使用して、少しスペースを取り戻すことができます。

DBCC SHRINKFILE (1,TRUNCATEONLY)

これにより、file_id = 1のデータベースファイルの最後に保持されているすべての空のデータページが切り捨てられます。140GBの例に戻ります。140GBデータベースファイルが最後に書き込まれたページを120GBの位置に保持している場合、最後の20GBはほぼ瞬時に戻ります。このプロセスはファイルエンドマーカーを120GBの位置に移動するだけで、オペレーティングシステムに空き容量を通知するため、非常に高速です。

次のクエリを使用して、データベースファイルの概要をすばやく取得できます。

SELECT *
FROM sys.sysfiles

十分な空きディスク領域がある場合(またはすべてのファイルでTRUNCATEONLYを実行した後)、データベースファイルを完全にクリーンアップして、実際に圧縮できるはずです。

これは、次のステートメントを使用して実現できます。

DBCC SHRINKFILE (1);

頻繁に書き込まれたり、より大きなトランザクションを実行したりするデータベーステーブルがある場合は、ターゲットの制限を定義することをお勧めします。これは、このデータベースの経験に依存します。通常は5〜10%(データベースのサイズによって異なります)ですが、100〜1000 MB以上を設定する必要があります。たとえば、140GBデータベースファイル(40GB空)の場合、ターゲットサイズは110GB(100GB使用+ 10%リザーブ)に設定する必要があります。

これは次のステートメントを使用して実現できます。

DBCC SHRINKFILE (1,112640); -- 110GB in MB

ただし、これは非常に長く実行される可能性があります(ファイルサイズとI/Oサブシステムによって異なります)。 I/Oサブシステムでより大きなワークロードを作成するので、このようなスクリプトを短いロード時間(多分一晩)で実行することをお勧めします。

本当にデータベースファイルをクリーンアップしたい場合は、すべてのインデックスと、断片化度が高いREBUILDまたはREORGANIZEすべてのインデックスをチェックすることをお勧めします。

開発マシンを使用している場合、または本当にリスクを冒す用意がある場合は、このステートメントを実行できます。データベース内のすべてのインデックスを反復処理して再構築します。

DECLARE @sql nvarchar(max), @sch nvarchar(max), @obj nvarchar(max), @ind nvarchar(max)

DECLARE cur CURSOR FOR
    SELECT s.name, o.name, i.name
    FROM sys.objects as o
    INNER JOIN sys.schemas as s
            ON o.schema_id = s.schema_id
    INNER JOIN sys.indexes as i
            ON o.object_id = i.object_id
    WHERE i.type > 0 

OPEN cur

FETCH NEXT FROM cur INTO @sch, @obj, @ind

WHILE @@FETCH_STATUS = 0 BEGIN

    SET @sql =  N'ALTER INDEX ['+@ind+'] ON ['+@sch+'].['+@obj+'] ' 
                + N'REBUILD PARTITION = ALL '
                + N'WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, '
                + N'ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)'
    PRINT(@sql) EXEC (@sql)

    FETCH NEXT FROM cur INTO @sch, @obj, @ind
END

CLOSE cur
DEALLOCATE cur

そのプロセスの後、データベースファイルが再び大きくなる可能性があります。ただし、すべてのインデックスの空き領域が削除されるため、ファイルサイズをはるかに小さくすることができます。

警告および追加情報

データベースファイルの圧縮には注意してください。 SQL Serverがファイルスペースを事前に割り当てるのには十分な理由があります。ディスクの割り当てはコストがかかるため、できるだけ少なくすることをお勧めします。毎日数GBのオーバーヘッドを生み出し、しばらくしてから解放する非常に機敏なデータベースがある場合、ファイルを常に最小に戻すのは良いことではありません。ファイルを拡張するためにディスクの電力を浪費し、ファイルを再び縮小するために、ディスクの電力を無駄に消費します。このような場合、データ操作を改善するためにビットディスク領域を浪費することに注意してください。

うまくいけば、この長い要約が問題の解決に役立ち、データベースの計画を立てるのにも役立ちます。

5
Ionic

[プロパティ]-> [ファイル]で初期サイズ設定を確認します。イニシャルは最小値を読み取る必要があります。空き領域がいくらあっても、それ以下に縮小することはできません。

4
Ethan Drotning

縮小する前に、最大のテーブルのクラスター化インデックスのページがいっぱいであることを確認する必要があります

Page fullness and fragmentation[ページの満杯と断片化]

再構築する Rebuild clustered index[クラスター化インデックスの再構築]

データファイルの縮小:タスク|縮小| SQL Server Management Studioの「未使用領域を解放する前にファイルを再編成」するファイル

追伸縮小後、パフォーマンスに影響を与える可能性のある高度に断片化されたデータベースが作成されることに注意してください

3
AlexK