24

サイズが約 4GB の SQL Server 2005 上のテーブルがあります。

(約1700万件)

フィールドの 1 つを datatypechar(30)からに変更しましたchar(60)(合計で 25 のフィールドがあり、そのほとんどがchar(10)char スペースの合計で約 300 になります)。

これにより、テーブルのサイズが 2 倍になりました (9 GB 以上)。

次に、をに変更しchar(60)varchar(60)データから余分な空白を削除する関数を実行しました (フィールド内のデータの平均長を約 15 に減らすため)。

これにより、テーブルのサイズが縮小されませんでした。データベースの縮小も役に立ちませんでした。

実際にテーブル構造を再作成してデータをコピーする以外に (つまり、1,700 万レコードです!)、サイズを元に戻すためのより抜本的な方法はありますか?

4

5 に答える 5

28

「データベースの縮小」を使用しても、データを消去または圧縮していません。

DBCC 洗浄可能

テーブルまたはインデックス付きビューで削除された可変長列から領域を再利用します。

ただし、クラスター化されたインデックスがある場合は、単純なインデックスの再構築 でもそれを行う必要があります

ALTER INDEX ALL ON dbo.Mytable REBUILD

トニー・ロジャーソンの実例

于 2009-04-30T18:22:55.510 に答える
20

スペースが戻っていないことは明らかです。:-)

テキスト フィールドを CHAR(60) に変更すると、すべてのフィールドがスペースでいっぱいになります。したがって、すべてのフィールドは実際には 60 文字の長さになります。

それを VARCHAR(60) に戻しても役に立ちません-フィールドはまだすべて60文字です....

実際に行う必要があるのは、すべてのフィールドに対して TRIM 関数を実行して、それらをトリミングされた長さに戻し、データベースの縮小を行うことです。

それが終わったら、その無駄なスペースの一部を再利用するために、クラスター化インデックスを再構築する必要があります。クラスター化インデックスは、実際にデータが存在する場所です。次のように再構築できます。

ALTER INDEX IndexName ON YourTable REBUILD 

既定では、主キーはクラスター化インデックスです (特に指定しない限り)。

マルク

于 2009-04-30T15:57:01.833 に答える
3

私はあなたが尋ねているようにあなたの質問に答えていないことを知っていますが、データの一部を履歴テーブルにアーカイブし、より少ない行で作業することを検討しましたか?

ほとんどの場合、一見すると常にすべてのデータが必要だと思うかもしれませんが、実際に座って調べてみると、そうでない場合があります。または、少なくとも私は以前にその状況を経験したことがあります。

于 2009-04-30T15:53:56.990 に答える
0

ここでも同様の問題が発生しました。SQLServerは、ntextをnvarchar(max)に変更することに関連するNTEXTをNVARCHAR(MAX)に変換します。

UPDATE MyTable SET MyValue = MyValueすべてをうまくサイズ変更するために、を実行する必要がありました。

これは明らかに、多くのレコードでかなり長い時間がかかります。それをどのように行うのが良いかとして、いくつかの提案がありました。それらの重要な1つは、それが行われたかどうかを示す一時的なフラグであり、すべてが完了するまでループで一度に数千を更新しました。これは、私がそれがどれだけ行っているかを「ある程度」制御できることを意味しました。

ただし、データベースを可能な限り縮小したい場合は、リカバリモデルを単純に縮小し、トランザクションログを縮小し、ページ内のすべてのデータを再編成してから、完全に戻すと役立ちます。リカバリーモデル。ただし、データベースを縮小することは一般的にはお勧めできません。ライブデータベースのリカバリモデルを減らすと、何か問題が発生する可能性があります。

于 2009-04-30T15:49:09.327 に答える
0

または、テーブル全体を再構築して、余分なデータがどこかにぶら下がっていないことを確認することもできます。

CREATE TABLE tmp_table(<column definitions>);
GO
INSERT INTO tmp_table(<columns>) SELECT <columns> FROM <table>;
GO
DROP TABLE <table>;
GO
EXEC sp_rename N'tmp_table', N'<table>';
GO

もちろん、ID、インデックスなどで事態はさらに複雑になります...

于 2009-04-30T15:59:35.010 に答える