次の方法で共有


DELETE ステートメントを使用して SQL Server のテーブルからデータを削除した後、テーブルで使用する領域が完全に解放されない

この記事は、DELETE ステートメントを使用してテーブルからすべてのデータを削除した後に、テーブルで使用される問題を回避するのに役立ちます。

元の製品バージョン: SQL Server
元の KB 番号: 913399

現象

Microsoft SQL Server で DELETE ステートメントを使用してテーブルからデータを削除すると、テーブルで使用される領域が完全には解放されないことがあります。 その後、データベースにデータを挿入しようとすると、次のエラー メッセージが表示されることがあります。

データベース 'DatabaseName' のオブジェクト 'TableName' に領域を割り当てませんでした。'PRIMARY' ファイル グループがいっぱいです。

Note

TableName はテーブルの名前を表します。 DatabaseName は、テーブルを含むデータベースの名前を表します。

原因

この問題は、次の条件に該当する場合に、SQL Server によってヒープ テーブルで使用されるすべてのページのみが解放されるために発生します。

  • このテーブルは削除されます。
  • テーブル レベルのロックが保持されています。

Note

ヒープ テーブルは、クラスター化インデックスに関連付けられていない任意のテーブルです。

ページの割り当てが解除されていない場合、データベース内の他のオブジェクトはページを再利用できません。

ただし、SQL Server データベースで行 versioning-based 分離レベルを有効にすると、テーブル レベルのロックが保持されている場合でもページを解放できません。 行versioning-based分離レベルの詳細については、「SQL Server データベース エンジンIsolation レベル」を参照してください。

回避策

この問題を回避するには、次のいずれかの方法を使用します。

  • 行のバージョン管理ベースの分離レベルが有効になっていない場合は、DELETE ステートメントに TABLOCK ヒントを含めます。 たとえば、次のようなステートメントを使用します。

    DELETE FROM <TableName> WITH (TABLOCK)
    

    Note

    <TableName> は、テーブルの名前を表します。

  • テーブル内のすべてのレコードを削除する場合は、TRUNCATE TABLE ステートメントを使用します。 たとえば、次のようなステートメントを使用します。

    TRUNCATE TABLE <TableName>
    
  • テーブルの列にクラスター化インデックスを作成します。 テーブルにクラスター化インデックスを作成する方法の詳細については、「 クラスター化インデックスの作成」を参照してください。