web-dev-qa-db-ja.com

テーブルフィールドを削除した後にディスク領域を要求する

私はsql 2008 r2を実​​行しており、dbは過去3年間、非常にアクティブで使用されているテーブルにntextフィールドを追加するまで、過去3年間は問題なく高速で動作していました。このテーブルのサイズが非常に大きくなるため、サーバースペースが不足し始めています。

私はそれが何年もの間速く働いていたので、そして断片化の拡張を取得したくないので、縮小のdbのインデックスを失うことを望まないことを読んだ。

そのフィールドとそのすべての値を削除することにしました:ntextフィールドとそのすべての値を削除し、インデックスを削除せずにスペースを解放する方法はありますか。 dbのパフォーマンスを失うことなく縮小していますか?

過去5か月のサイズ拡張を示すために、dbサイズクエリ出力を添付しています。

enter image description here

16
user1021182

そのフィールドとそのすべての値を削除することにしました。ntextフィールドとそのすべての値を削除し、インデックスを削除せずに、スペースを解放し、dbのパフォーマンスを失うことなく、縮小する方法はありますか?

(BOLから))を使用することをお勧めします

DBCC CLEANTABLE
(
    { database_name | database_id | 0 }
    , { table_name | table_id | view_name | view_id }
    [ , batch_size ]
)
[ WITH NO_INFOMSGS ]

DBCC CLEANTABLEは、可変長の列が削除された後にスペースを再利用します。可変長列は、varchar、nvarchar、varchar(max)、nvarchar(max)、varbinary、varbinary(max)、text、ntext、image、sql_variant、xmlのいずれかのデータ型になります。固定長の列が削除された後、コマンドはスペースを再利用しません。

!! [〜#〜]注意[〜#〜]!! 注意してバッチサイズを使用してください-テーブルが大きい場合は、このパラメーターを使用することをお勧めします)

DBCC CLEANTABLEは、1つ以上のトランザクションとして実行されます。バッチサイズが指定されていない場合、コマンドは1つのトランザクションでテーブル全体を処理し、テーブルは排他的にロックされます操作中。一部の大きなテーブルでは、単一トランザクションの長さと必要なログ領域が多すぎる場合があります。バッチサイズが指定されている場合、コマンドは一連のトランザクションで実行され、各トランザクションには指定された行数が含まれます。 DBCC CLEANTABLEは、別のトランザクション内のトランザクションとして実行することはできません。

この操作は完全にログに記録されます。

簡単な再現は、そのことを証明しますDBCC CLEANTABLEは収縮よりも優れています(そして断片化の心配はありません:-)

-- clean up
drop table dbo.Test

-- create test table with ntext column that we will drop later
create table dbo.Test (
    col1 int
    ,col2 char(25)
    ,col3 ntext
    );

-- insert  1000 rows of test data
declare @cnt int;

set @cnt = 0;

while @cnt < 1000
begin
    select @cnt = @cnt + 1;

    insert dbo.Test (
        col1
        ,col2
        ,col3
        )
    values (
        @cnt
        ,'This is a test row # ' + CAST(@cnt as varchar(10)) + 'A'
        ,REPLICATE('KIN', ROUND(Rand() * @cnt, 0))
        );
end

enter image description here

enter image description here

--drop the ntext column
ALTER TABLE dbo.Test DROP COLUMN col3 ;

enter image description here

enter image description here

--reclaim the space from the table
-- Note that my table is only having 1000 records, so I have not used a batch size
-- YMMV .. so find a maintenance window and you an appropriate batch size 
-- TEST TEST and TEST before implementing in PROD.. so you know the outcome !!
DBCC CLEANTABLE('tempdb', 'dbo.Test') ;

enter image description here

enter image description here

12
Kin Shah

ほとんどの部分で、Paul Randallの In the storage engine ブログシリーズを参照しています。

SQLServerのデータベースファイルから未使用の領域を再利用する唯一の方法は、データベースファイル内のデータを再割り当てするDBCC SHRINKコマンドを使用して、ページを解放し、グローバルAllcationマップから削除した後、データベースファイルからそれらを削除することです。この操作は低速で、データベース内で断片化を引き起こし、LOBページをリンクされたリストとしてデータベースファイル内に格納するため、LOBページを処理する場合はさらに遅くなります。

NTEXT列をドロップしているので、ゴーストクリーンアッププロセスがデータをドロップしてから縮小するまで待つ必要があります。

データベースファイルに多くの空き領域があっても、実際には害はありません。ディスク領域があれば、バックアップ圧縮がファイル内の空き領域を処理します。

ファイルを小さくしたい場合は、データベースを使用して新しいファイルグループを作成し、それをデフォルトにしてから、テーブルを新しいファイルグループに移動しますが、これには時間がかかり、ダウンタイムが発生する可能性があります。私は説明したテクニックを使用しました ここではボブ・プサテリによる 良い結果が得られました。

6
Spörri

他のデータベース/非DBファイル用のスペースが必要なため、またはこのデータベースでスペースが不足する問題が発生しているため、データベースファイルを縮小しますか?

2番目の場合は、思ったほど大きな問題ではない可能性があります。私が正しければ、問題は、新しいデータ用に追加のスペースを確保するためにデータベースを拡張する必要があるときです。列を削除すると、その列によって占められていたすべてのスペースが解放され、新しい行をデータベース内のテーブルに追加できるようになります。これは、データベースを拡張する必要がある前に長くなることを意味します。それまでの間、データドライブ用に追加のスペースを確保します。ほとんどのデータベースは時間の経過とともに大きくなり、ドライブの空き領域に十分な余裕があるのは素晴らしいことです。

4
Kenneth Fisher

問題の列がないミラーテーブルを作成し、すべてのデータをこのテーブルにコピーして、元のテーブルを削除してから、ミラーテーブルの名前を変更します。

0
ardochhigh