適用対象:Azure SQL データベース
この記事では、Azure SQL Database のデータベースのさまざまな種類のストレージ領域について説明します。 時には割り当てられたファイル空間を明示的に管理する必要があるかもしれません。 この記事では、その手順を紹介します。
概要
特定のワークロードパターンにより、データファイルに割り当てられた容量が使用済みの領域より大きくなることがあります。 この状態は、データの増加により使用容量が増えたものの、後にデータを削除または圧縮する場合に発生します。 割り当てられたが未使用のスペースは自動的に回収されません。なぜなら、回収はリソースを消費し、将来のファイル成長を遅らせるからです。
以下の状況では、データファイルを縮小し、未使用の領域を取り戻す必要があるかもしれません:
- エラスティックプール内のデータベースのデータ成長を可能にするため、プール内の一部のデータベースに割り当てられた大きな容量がプールの最大サイズに近づく場合に対応できます。
- 単一のデータベースやエラスティックプールの最大サイズを削減するために。
- データベースやエラスティックプールを、最大サイズ制限を下げるティアに変更することです。
- ハイパースケールサービス層を使用する際のストレージコスト削減。
注意事項
縮小手術を定期的なメンテナンスと考えないでください。 定期的な定期的なビジネス操作によって拡大するデータ ファイルとログ ファイルでは、縮小操作は必要ありません。
ファイル領域の使用状況の監視
Azure Resource Manager(ARM)APIは、PowerShellのget-metricsを含め、データベースやelastic poolのために使用済みおよび割り当てられた領域を返します。
以下のシステムビューは、データベースおよびエラスティックプールの使用済みおよび割り当てされた容量も返します。
データベースの記憶域スペースの種類を理解する
データベースのファイル領域を管理するには、次のストレージ領域の量を理解することが重要です。
| データベースの量 | 定義 | コメント |
|---|---|---|
| 使用済みのデータ領域 | データを保存するために使われる容量。 | 一般的に、使用済みの領域は挿入 (削除) で増加 (減少) します。 場合によっては、操作に関係するデータの量とパターンや断片化に応じて、挿入または削除で使用される領域が変わらない場合があります。 たとえば、すべてのデータ ページから 1 行を削除しても、使用領域が減らない場合があります。 |
| 割り当て済みのデータ領域 | データファイルが占めるストレージ容量。 | 割り当てられた容量は自動的に増加しますが、削除後に自動的に減少することはありません。 この動作により、スペースの再割り当てが不要になり、将来の挿入がより速くなります。 |
| 割り当て済みで未使用のデータ領域 | 割り当て済みのデータ領域と使用済みのデータ領域の差。 | この量は、データベースのデータ ファイルを縮小して再利用できる空き領域の上限を表します。 |
| データの最大サイズ | データを保存するために使用できる最大容量。 | データの最大サイズを超えて、割り当て済みのデータ領域の量を増やすことはできません。 |
次の図は、データベースの異なる種類の記憶域スペース間の関係を示しています。
ファイル領域の情報について単一データベースのクエリを実行する
sys.database_files に次のクエリを使用して、割り当て済みデータベース ファイル領域と未使用の割り当て済み領域を返します。
-- Connect to a user database
SELECT file_id,
type_desc,
CAST (FILEPROPERTY(name, 'SpaceUsed') AS DECIMAL (19, 4)) * 8 / 1024. AS space_used_mb,
CAST (size / 128.0 - CAST (FILEPROPERTY(name, 'SpaceUsed') AS INT) / 128.0 AS DECIMAL (19, 4)) AS space_unused_mb,
CAST (size AS DECIMAL (19, 4)) * 8 / 1024. AS space_allocated_mb,
CAST (max_size AS DECIMAL (19, 4)) * 8 / 1024. AS max_size_mb
FROM sys.database_files;
エラスティック プールの記憶域スペースの種類を理解する
以下のストレージ容量を理解することは、エラスティックプールのファイル空間管理に重要です。
| エラスティック プールの量 | 定義 | コメント |
|---|---|---|
| 使用済みのデータ領域 | エラスティック プール内のすべてのデータベースで使用されるデータ領域の合計。 | |
| 割り当て済みのデータ領域 | エラスティックプール内のすべてのデータベースでデータファイルが占めるストレージ容量の合計です。 | |
| 割り当て済みで未使用のデータ領域 | エラスティック プール内のすべてのデータベースで割り当て済みのデータ領域と使用済みのデータ領域の差。 | この量は、データベースのデータ ファイルを縮小して再利用できる、エラスティック プールに割り当てられた領域の上限を表します。 |
| データの最大サイズ | エラスティック プールのすべてのデータベースに使用するデータ領域の最大量。 | 弾性プールに割り当てられるスペースは、弾性プールの最大サイズを超えてはいけません。 この条件が発生した場合、割り当てられたが未使用のデータは縮小ファイルによって回収できます。 |
エラーメッセージ「The elasticpool has reached its storage limit(エラスティックプールはストレージ上限に達しました)」は、データベースオブジェクトがエラスティックプールの最大ストレージサイズ制限を満たすだけのスペースを使用していることを示しています。 ストレージ制限の増やし、未 使用割り当て領域の回収で説明されているデータスペースの解放を検討してください。
記憶域スペースの情報についてエラスティック プールのクエリを実行する
以下のクエリを使って、弾力性プールのストレージ容量を算出します。
エラスティック プールで使用されたデータ領域
以下の例クエリを使って、使用された弾力プールのデータ空間の量を返します。 弾力性プール名パラメータをプール名に合わせて変更します。
-- Connect to master
SELECT TOP (1) avg_storage_percent / 100.0 * elastic_pool_storage_limit_mb AS elastic_pool_space_used_mb,
avg_allocated_storage_percent / 100.0 * elastic_pool_storage_limit_mb AS elastic_pool_space_allocated_mb,
elastic_pool_storage_limit_mb AS elastic_pool_maximum_size_mb
FROM sys.elastic_pool_resource_stats
WHERE elastic_pool_name = 'ep1'
ORDER BY end_time DESC;
未使用の割り当て済み領域を再利用する
重要
シュリンク操作はリソースを消費し、実行中のデータベースパフォーマンスに影響を与えることがあります。 可能であれば、利用が少ない時間帯に縮小処理を実行してください。
データ ファイルを圧縮する
データファイルの縮小はデータベースのパフォーマンスに影響を与えるため、Azure SQL Databaseは自動的にデータファイルを縮小しません。 必要に応じて、好きなタイミングでデータファイルを縮小することも可能です。 在庫減耗への対応を、定期的な業務にしないでください。 代わりに、使用スペースを大幅に減らした後にだけ使用することを検討してください。
ヒント
通常のアプリケーションの負荷でファイルが同じ割り当てサイズに増えてしまうなら、計算リソースや時間の無駄なデータファイルの縮小は避けましょう。
ファイルを縮小するには、 DBCC SHRINKDATABASE または DBCC SHRINKFILE T-SQLコマンドを使用します。
-
DBCC SHRINKDATABASE単一のコマンドでデータベース内のすべてのデータとログファイルを縮小します。 このコマンドによって、一度に 1 つのデータ ファイルが圧縮されます。より大規模なデータベースでは時間がかかる場合があります。 また、ログ ファイルも縮小されます。Azure SQL Database によって必要に応じてログ ファイルが自動的に圧縮されるため、これは通常は不要です。 -
DBCC SHRINKFILEコマンドでは、より高度なシナリオがサポートされます。- データベース内のすべてのファイルを圧縮するのではなく、必要に応じて個々のファイルを対象にすることができます。
- 各
DBCC SHRINKFILEコマンドは他のDBCC SHRINKFILEコマンドと並列実行することでシュリンクの総時間を短縮できますが、その代償としてリソース使用量の増加や、ユーザークエリや同時処理DBCC SHRINKFILEコマンドが一時的にブロックされるリスクが高まります。 - ファイルの尾部にデータが含まれていない場合、
TRUNCATEONLY引数を指定することで割り当てられたファイルサイズをより速く削減できます。TRUNCATEONLYファイル内でのデータ移動を必要としませんが、割り当てられたサイズもそれほど減らしません。
- これらの圧縮コマンドの詳細については、「DBCC SHRINKDATABASE」と「DBCC SHRINKFILE」を参照してください。
以下の例は、 master データベースではなくターゲットユーザーデータベースに接続した状態で実行してください。
DBCC SHRINKDATABASE を使用して、特定のデータベースのすべてのデータ ファイルとログ ファイルを圧縮するには、次のようにします。
DBCC SHRINKDATABASE (N'database_name');
データベースには、データが増えるにつれて自動的に作成される1つ以上のデータファイルが存在する場合があります。 データベースのファイルレイアウト(各ファイルの使用済みおよび割り当てサイズを含む)を決定するには、以下の例スクリプトを使って sys.database_files カタログビューを照会します。
-- Review file properties, including the file_id and name values to use in shrink commands
SELECT file_id,
name,
CAST (FILEPROPERTY(name, 'SpaceUsed') AS BIGINT) * 8 / 1024. AS space_used_mb,
CAST (size AS BIGINT) * 8 / 1024. AS space_allocated_mb,
CAST (max_size AS BIGINT) * 8 / 1024. AS max_file_size_mb
FROM sys.database_files
WHERE type_desc IN ('ROWS', 'LOG');
単一のファイルを縮小するには、例えば DBCC SHRINKFILE コマンドを使ってください:
-- Shrink database data file named 'data_0` by removing all unused at the end of the file, if any.
DBCC SHRINKFILE ('data_0', TRUNCATEONLY);
トランザクション ログ ファイルの圧縮
データ ファイルとは異なり、Azure SQL Database では、領域不足エラーが発生する可能性のある領域の過剰使用を防ぐために、トランザクション ログ ファイルが自動的に圧縮されます。 ほとんどの場合、トランザクション ログ ファイルを圧縮する必要はありません。
プレミアムおよびビジネスクリティカルサービス層では、トランザクションログが大きくなると、 最大ローカルストレージ の限界に近づくローカルストレージ消費に大きく寄与する可能性があります。 ローカルストレージ消費が限界に近い場合は、以下の例のように DBCC SHRINKFILE コマンドを使ってトランザクションログを縮小することを選択できます。 これにより、定期的な自動圧縮操作を待たずに、コマンドが完了するとすぐにローカル ストレージが解放されます。
以下の例は、 master データベースではなくターゲットユーザーデータベースに接続した状態で実行してください。
-- Shrink the database log file (always file_id 2), by removing all unused space at the end of the file, if any.
DBCC SHRINKFILE (2, TRUNCATEONLY);
自動圧縮
データ ファイルを手動で圧縮する代わりに、データベースに対して自動圧縮を有効にすることができます。 ただし、自動圧縮は、DBCC SHRINKDATABASE および DBCC SHRINKFILE よりもファイル領域の解放の効果が低くなる可能性があります。
既定では、自動圧縮は無効になっています。これは、ほとんどのデータベースで推奨されます。 自動縮小を有効にする必要が生じた場合は、スペース管理目標を達成したら、永久に有効にするのではなく無効にすることが推奨されます。 詳細については、「AUTO_SHRINK に関する考慮事項」を参照してください。
例えば、エラスティック プールに多数のデータベースが含まれており、それらの使用済み領域が継続的に大幅な増減を繰り返した結果、プールが最大サイズ制限に近づくような場合には、自動縮小が役立つことがあります。 このシナリオは一般的ではありません。
自動縮小データベースオプションはハイパースケールデータベースには効果がありません。
自動圧縮を有効にするには、(master データベースではなく) 対象のデータベースに接続しているときに次のコマンドを実行します。
-- Enable auto-shrink for the current database.
ALTER DATABASE CURRENT
SET AUTO_SHRINK ON;
このコマンドの詳細については、DATABASE SET オプションをご覧ください。
圧縮後のインデックスのメンテナンス
縮小操作が完了すると、インデックスが断片化されることがあります。 現代のほとんどのワークロードでは、インデックス断片化がパフォーマンスに影響を与える可能性は低いです。 大規模なインデックススキャンを使用するワークロードでは、断片化が読み取りI/Oスループットを低下させる可能性があります。 縮小操作完了後にパフォーマンス低下が発生した場合は、インデックスの再構築や再編成のためにインデックスメンテナンスを検討してください。 インデックスの再構築はデータベースの空き容量を必要とするため、割り当てられた容量が増加し、縮小の効果を相殺することがあります。
インデックスのメンテナンスの詳細については、「クエリのパフォーマンスを向上させてリソースの消費を削減するためにインデックスのメンテナンスを最適化する」を参照してください。
大規模なデータベースを圧縮する
データベース内の割り当て容量が数百ギガバイト以上の場合、縮小には長い時間がかかることがあります。 数テラバイト規模のデータベースでは、シュリンク作業は数時間、数日、あるいは数週間に及ぶことがあります。 このセクションでは、プロセスの最適化とベストプラクティスを説明し、このプロセスをより効率的かつアプリケーションワークロードへの影響を軽減するためのものです。
ヒント
ShrinkDriver は、大規模データベースの縮小プロセスを自動化・簡素化し、単一の観察可能かつ再開可能な操作に変えるPowerShellスクリプトです。 スクリプトは複数のファイルを並列に縮小し、中断されると再試行し、実行中に詳細なステータスレポートを出力します。
領域の使用状況のベースラインをキャプチャする
圧縮を開始する前に、次の領域の使用状況クエリを実行して、各データベース ファイルで現在使用されている領域と割り当てられた領域をキャプチャします。
SELECT file_id,
CAST (FILEPROPERTY(name, 'SpaceUsed') AS BIGINT) * 8 / 1024. AS space_used_mb,
CAST (size AS BIGINT) * 8 / 1024. AS space_allocated_mb,
CAST (max_size AS BIGINT) * 8 / 1024. AS max_size_mb
FROM sys.database_files
WHERE type_desc = 'ROWS';
圧縮が完了したら、このクエリを再度実行し、結果を最初のベースラインと比較できます。
データファイルを切り詰めると、高速ですが限定的な性能向上が得られます
割り当てられた領域を素早く減らしたいなら、DBCC SHRINKFILEパラメータでTRUNCATEONLYを実行することを検討してください。 ファイルの最後に割り当てられているが使われていない領域があれば、その領域を素早く、データ移動なしで削除します。
ただし、割り当てられたスペースの削減を最大化することが目的なら TRUNCATEONLY は使わないでください。 その目的を達成するためには、このセクションの後半で説明する完全な縮小プロセスを実行する必要があります。 このプロセスはファイルの最後で切り捨てるため、別途 TRUNCATEONLY で縮小してもメリットはありません。
以下の例コマンドはファイルID 4を切り詰めます:
DBCC SHRINKFILE (4, TRUNCATEONLY);
すべてのデータファイルに対してこのコマンドを実行した後、割り当てられたスペースの減少があれば、スペース使用クエリを再実行してください。 また、Azureポータルでデータベースの割り当てされた容量を確認することもできます。
インデックス ページの密度を評価する
オプションですが推奨されるステップとして、データベース内のインデックスの平均ページ密度を決定してください。 同じデータ量の場合、ページ密度が高いほど縮小操作はより速く完了します。なぜなら、各ファイル内の移動ページ数が少ないためです。 一部のインデックスでページの密度が低い場合は、データ ファイルを圧縮する前に、これらのインデックスのメンテナンスを実行してページ密度を増やすことを検討してください。 ページ密度を上げることで、割り当てられたストレージ容量をより大きく削減できます。
データベース内のすべてのインデックスのページ密度を判別するには、次のクエリを使用します。 ページ密度は avg_page_space_used_in_percent 列で報告されます。
SELECT OBJECT_SCHEMA_NAME(ips.object_id) AS schema_name,
OBJECT_NAME(ips.object_id) AS object_name,
i.name AS index_name,
i.type_desc AS index_type,
ips.avg_page_space_used_in_percent,
ips.avg_fragmentation_in_percent,
ips.page_count,
ips.alloc_unit_type_desc,
ips.ghost_record_count
FROM sys.dm_db_index_physical_stats(DB_ID(), DEFAULT, DEFAULT, DEFAULT, 'SAMPLED') AS ips
INNER JOIN sys.indexes AS i
ON ips.object_id = i.object_id
AND ips.index_id = i.index_id
ORDER BY page_count DESC;
ページ数が多いインデックス( page_count 列に報告されている)でページ密度が60〜70%未満の場合は、データファイルを縮小する前にこれらのインデックスを再構築または再編成することを検討してください。
大規模なデータベースの場合、ページ密度を判断するクエリの完了に時間がかかる場合があります。 大規模なインデックスを再構築または再構成するには、時間とリソースの使用量も大幅に必要です。 ただし、圧縮前のインデックスメンテナンスは、圧縮期間を短縮し、より高いスペース節約を実現できます。
ページ密度が低いインデックスが複数ある場合、複数のデータベース セッションで並行して再構築し、プロセスを高速化できる場合があります。 ただし、データベースのリソース制限に近づかないように注意してください。 実行中の可能性があるアプリケーション ワークロードに十分なリソース ヘッドルームを残します。 リソース消費(CPU、データIO、ログIO)をAzureポータルまたはsys.dm_db_resource_statsビューで監視してください。 これらの次元ごとのリソース利用率が100%を大幅に下回る場合にのみ、追加のインデックス操作を開始してください。
インデックス再構築コマンドの例
以下の例命令は 、ALTER INDEX 文を使ってインデックスを再構築し、ページ密度を増加させます:
ALTER INDEX [index_name] ON [schema_name].[table_name]
REBUILD WITH (
FILLFACTOR = 100, MAXDOP = 8, ONLINE = ON (
WAIT_AT_LOW_PRIORITY (MAX_DURATION = 5 MINUTES, ABORT_AFTER_WAIT = NONE)),
RESUMABLE = ON
);
このコマンドによって、オンラインの再開可能なインデックスの再構築が開始されます。 この操作により、再構築の進行中に同時実行ワークロードでテーブルの使用を継続でき、何らかの理由で中断された場合に再構築を再開できます。 ただし、この種類の再構築は、テーブルへのアクセスをブロックするオフラインの再構築よりも低速です。 再構築中に他のワークロードからテーブルにアクセスする必要がない場合は、ONLINE および RESUMABLE オプションを OFF に設定し、WAIT_AT_LOW_PRIORITY 句を削除します。
インデックスのメンテナンスの詳細について学習するには、「クエリのパフォーマンスを向上させてリソースの消費を削減するためにインデックスのメンテナンスを最適化する」を参照してください。
縮小する前にインデックスを再編成する
縮小前にインデックスを再編成することで、縮小操作を大幅に高速化できます。
データベースが以下のすべての条件を満たしている場合:
- 10件以上の多くのデータファイルを持っています。
- データベースには数百以上のテーブルがあり、合計で数百ギガバイト以上の大量のスペースを消費します。
- 一部のテーブルから大量のデータが削除されます。
このようなデータベースでは、データを削除したテーブルのインデックスを再整理することで、縮小プロセスの長期的なフェーズを短縮できます。
データベースに以下が含まれている場合:
-
varchar(max)、nvarchar(max)、varbinary(max)、xmlなどのラージオブジェクト(LOB)データ型が
LOB_DATA割り当てユニットに保存されます。 -
大きな行が
ROW_OVERFLOW_DATA。 - 列ストア インデックス。
この状況で縮小を高速にし、より多くのスペースを解放するために、インデックスを再編成する際に
LOB_COMPACTION節を含めるようにしてください。 LOB 列や大きな行を含むすべてのインデックスについて、縮小の前に LOB 圧縮を行うことをお勧めします。圧縮前に列ストア インデックスを再構成または再構築すると、同様に圧縮速度と有効性が向上する可能性があります。
-
varchar(max)、nvarchar(max)、varbinary(max)、xmlなどのラージオブジェクト(LOB)データ型が
以下の例は、インデックスを再編成しLOB圧縮を実行するコマンドを示しています:
ALTER INDEX [index_name] ON [schema_name].[table_name]
REORGANIZE WITH(LOB_COMPACTION = ON);
複数のデータファイルを並列に縮小する
データの移動を必要とする縮小操作は長期的なプロセスです。 データベースに複数のデータ ファイルがある場合は、複数のデータ ファイルを並行して圧縮することで、プロセスを高速化できます。 複数のデータベース セッションを開き、異なるDBCC SHRINKFILE値を持つ各セッションでfile_idを使用します。 上記のインデックスの再構築と同様に、新しいそれぞれの並列圧縮コマンドを開始する前に、十分なリソース ヘッドルーム (CPU、データ IO、ログ IO) を確保してください。
以下の例はファイルID 4を縮小し、割り当てられたサイズを52,000 MBに減らそうとします。
DBCC SHRINKFILE (4, 52000);
ファイルの割り当て容量を可能な限り最小に減らすには、目標サイズを指定せずに文を実行します:
DBCC SHRINKFILE (4);
並行して多数の縮小操作を開始すると、リソース使用率が高くなり、縮小操作間でロック競合が発生することがあります。 ほとんどのシナリオにおいて、最適な並列縮小操作の回数は4回から8回の範囲です。
段階的に縮小する
シュリンク操作が予期せず停止した場合(例えば、計画的または未計画のメンテナンスによる場合)、シュリンクがファイルを切り捨てる前に、作業負荷が解放されたスペースを使い始め、これまでの進捗シュリンクの一部を失うことがあります。 shrink は長時間実行されることが多いため、中断が発生する可能性が高くなります。
この問題を避けるために、各ファイルを小さく段階的に縮小してください。
DBCC SHRINKFILEコマンドで、ファイルに現在割り当てられている領域より小さいが、ベースラインのスペース使用クエリが返す使用済み領域より大きいターゲットを設定します。
例えば、ファイルID 4の割り当て容量が200,000MBで、それを100,000MBに縮小したい場合、まずターゲットを180,000MBに設定できます。
DBCC SHRINKFILE (4, 180000);
このコマンドで割り当てられたサイズを180,000MBに減らした後、再度縮小を実行し、まずターゲットを160,000MB、次に140,000MBに設定し、ファイルが希望のサイズに達するまでターゲットを縮小し続けます。
ファイルを段階的に縮小すると時間がかかるかもしれませんが、予期せぬ中断によってファイル全体にわたって繰り返し縮小するリスクを減らせます。
まずは10〜20ギガバイトの範囲で増分を使いましょう。 状況に応じて増分を調整できます。 大きな増分はファイルの縮小を早く完了させ、小さな増分は縮小が中断された場合の進行状況を失うリスクを減らせます。
圧縮操作を監視する
同時に実行中のすべてのシュリンクセッションのシュリンク進捗を監視するには、以下のクエリを使用します。
SELECT command,
percent_complete,
status,
wait_resource,
session_id,
wait_type,
blocking_session_id,
cpu_time,
reads,
writes,
CAST (((DATEDIFF(s, start_time, GETDATE())) / 3600) AS VARCHAR) + ' hour(s), '
+ CAST ((DATEDIFF(s, start_time, GETDATE()) % 3600) / 60 AS VARCHAR) + 'min, '
+ CAST ((DATEDIFF(s, start_time, GETDATE()) % 60) AS VARCHAR) + ' sec'
AS running_time
FROM sys.dm_exec_requests AS r
LEFT OUTER JOIN sys.databases AS d
ON r.database_id = d.database_id
WHERE r.command IN ('DbccSpaceReclaim', 'DbccFilesCompact', 'DbccLOBCompact', 'DBCC');
Note
縮小の進行は非線形で、 percent_complete 列の値は縮小が進行中であっても長期間変わらないことがあります。 同じsession_idについて、クエリの2回の実行の間でcpu_time、reads、またはwritesの値が増加している場合、shrink が引き続き進捗していることを意味します。
すべてのデータファイルの縮小が正常に完了したら、スペース使用クエリを再実行するか(Azureポータルで確認)すると、割り当てられたストレージサイズの減少を確認します。 使用済みスペースと割り当て済みスペースに大きな差があるなら、インデックスを再 構築 または 再編成 してください。 インデックスの再構築は一時的に割り当てられた容量を増やすかもしれません。 しかし、インデックスを再構築後に再びデータファイルを縮小すると、割り当てられた容量がさらに大幅に減少することがよくあります。
圧縮中の一時的なエラー
時折、タイムアウトやデッドロックなどのエラーで縮小コマンドが失敗することがあります。 これらのエラーは一時的なものが多く、同じコマンドを繰り返すと再発しません。 縮小処理がエラーで失敗した場合でも、それまでの進捗は保持されます。 同じ圧縮コマンドをもう一度実行して、ファイルの圧縮を続行します。
ShrinkDriverのPowerShellスクリプトは、一時的なエラーが発生すると自動的にシュリンクを再試行します。 このスクリプトを使って大規模なデータベースを縮小できます。
以下の例T-SQLスクリプトは、リトライループで単一のファイルのシュリンクを実行する方法を示しています。 ループはタイムアウトエラーやデッドロックエラーが発生した場合、設定可能な回数まで自動的に操作を再試行します。 この再試行方法は、シュリンク中に起こりうる多くの他のエラーにも適用されます。
DECLARE @RetryCount AS INT = 3; -- adjust to configure desired number of retries
DECLARE @Delay AS CHAR (12);
-- Retry loop
WHILE @RetryCount >= 0
BEGIN
BEGIN TRY
DBCC SHRINKFILE (1); -- adjust file_id and other shrink parameters
-- Exit retry loop on successful execution
SELECT @RetryCount = -1;
END TRY
BEGIN CATCH
-- Retry for the declared number of times without raising
-- an error if deadlocked or timed out waiting for a lock
IF ERROR_NUMBER() IN (1205, 49516) AND @RetryCount > 0
BEGIN
SELECT @RetryCount -= 1;
PRINT CONCAT('Retry at ', SYSUTCDATETIME());
-- Wait for a random period of time between 1 and 10 seconds before retrying
SELECT @Delay = '00:00:0' + CAST (CAST (1 + RAND() * 8.999 AS DECIMAL (5, 3)) AS VARCHAR (5));
WAITFOR DELAY @Delay;
END
ELSE -- Raise error and exit loop
BEGIN
SELECT @RetryCount = -1;
THROW;
END
END CATCH
END
タイムアウトやデッドロックに加え、シュリンクは既知の問題によるエラーに遭遇することがあります。
以下のセクションの誤りと緩和手順を確認してください。
エラー番号49503
%.*ls: Page %d:%d could not be moved because it is an off-row persistent version store page. Page holdup reason: %ls. Page holdup timestamp: %I64d.
このエラーは、長時間実行中のアクティブなトランザクションが永続バージョンストア(PVS)で行バージョンを生成する際に発生します。 Shrinkは行バージョンを含むページを移動できません。
このエラーを軽減するために、長期間実行されたトランザクションが完了するまで待ちましょう。 あるいは、長期実行中のトランザクションを特定して終了する方法もありますが、この操作はトランザクション失敗をうまく処理しない場合、アプリケーションに影響を及ぼす可能性があります。
シュリンクに影響する可能性がある PVS クリーンアップ遅延のトラブルシューティングの詳細については、高速データベース復旧の監視とトラブルシューティングを参照してください。
エラー番号5223
%.*ls: Empty page %d:%d could not be deallocated.
このエラーは、 ALTER INDEXなどのインデックス保守作業中に発生することがあります。 これらの操作が完了したら、圧縮コマンドを再度試します。
このエラーが続く場合は、関連するインデックスを再構築する必要があるかもしれません。 再構築するインデックスを見つけるには、圧縮コマンドを実行したのと同じデータベースで次のクエリを実行します。
SELECT OBJECT_SCHEMA_NAME(pg.object_id) AS schema_name,
OBJECT_NAME(pg.object_id) AS object_name,
i.name AS index_name,
p.partition_number
FROM sys.dm_db_page_info(DB_ID(), <file_id>, <page_id>, default) AS pg
INNER JOIN sys.indexes AS i
ON pg.object_id = i.object_id
AND
pg.index_id = i.index_id
INNER JOIN sys.partitions AS p
ON pg.partition_id = p.partition_id;
このクエリを実行する前に、 <file_id> と <page_id> のプレースホルダーをエラーメッセージの実際の値に置き換えてください。 例えば、メッセージが「 Empty page 1:62669 could not be deallocated」であれば、 <file_id> は 1 、 <page_id> は 62669です。
クエリで識別されたインデックスを再構築し、圧縮コマンドを再度試します。
エラー番号5201
DBCC SHRINKDATABASE: File ID %d of database ID %d was skipped because the file does not have enough free space to reclaim.
このエラーにより、データファイルはこれ以上縮小できません。 次のデータ ファイルに移動できます。