web-dev-qa-db-ja.com

varchar列のサイズを小さくすると、データベースファイルにどのような影響がありますか?

データベースにはVARCHAR(MAX)列を持つテーブルがいくつかあり、VARCHAR(500)(またはmaxよりはるかに小さいもの)で十分です。当然、私はこれらをクリーンアップし、サイズをより妥当なレベルに下げたいと思っています。これを行う「方法」は理解しています:私の質問はこれらの列をディスク上のページとエクスタントに変更するとどうなりますか?(列を拡張するとどうなるかについての情報はたくさんあります。しかし、縮小するとどうなるかについての情報を見つけるのに苦労します。)

一部のテーブルは行数が非常に少ないため、変更のコストについては心配していませんが、かなり大きいテーブルもあり、それらが再編成されてブロッキング/ダウンタイムが大量に発生する可能性があることを心配しています。実際には、メンテナンスウィンドウを推定する方法が欲しいだけです。一般に、この場合のデータベースエンジンの動作をよく理解したいと思います。

前もって感謝します!

編集:

私が調べているテーブルは20ありますが、行カウントが1,000を超えるのはそのうちの半分だけです。最大のものはほぼ100万行です。最悪の違反者は、350,000行と4つのVARCHAR(MAX)列を持つテーブルで、VARCHAR(500)レベルに縮小できます。

15
nateirvin

まず最初に:テーブルにはどのくらいのデータがありますか?行の数とテーブルのサイズは?

次に、このテーブルをテストサーバーにバックアップおよび復元し、alterステートメントを実行して影響を確認できますか(テーブルが大きすぎて非運用システムに収まらないために実行不可能ではないと想定)。私の環境でのテストは、Webからのアドバイスよりも正確であることが常にわかります。これらの要因が結果に影響を与える可能性があることを知らないために、質問で提供されない可能性がある結果に影響を与える可能性があるいくつかの要因があるためです。

3番目:増加可変長フィールドのサイズ(8060バイトの制限を超えない場合)そのような操作で実際のデータは変更されないため、単純なメタデータ操作。しかし、一方で、reduce可変長フィールドのサイズは、明らかに機能する以上のものであっても、ではありませんすべての行をスキャンする前に、SQL Serverは新しく要求されたサイズが有効であることを認識していないため、単純なメタデータの変更。

したがって:はい、これはテーブルを一定期間ロックします。どのくらいの時間?さて、これが私がやったテストです:

他のいくつかのテストから、単一のINT NOT NULLフィールドと100万行のテーブルがありました。このテストを行うために、次のように新しいテーブルにコピーしました。

SELECT *, CONVERT(NVARCHAR(MAX), NEWID()) AS [StringField]
INTO dbo.ResizeTest
FROM dbo.ClusteredUnique;

このようにして、MAXフィールドを持つ同様のシナリオから始めました(VARCHARがあり、NVARCHARを使用していることに気付きましたが、次に、500に変更できることを確認しています。また、500文字以内で簡単に収まるデータが含まれています。それには数分かかりました。

次に実行しました:

ALTER TABLE dbo.ResizeTest ALTER COLUMN [StringField] NVARCHAR(500) NULL;

そして、それはちょうど11分以上かかりました。

私はもう一度テストを再実行しました。今回は[ResizeTest]テーブルを削除し、両方のNVARCHARsをVARCHARに変更しました。少なくともApple ;-)のように見えるもの。

最初のテーブルの作成には20秒かかりましたが、ALTER TABLEには2分かかりました。

したがって、ダウンタイムの見積もりに関しては、データファイルやトランザクションログなどで自動拡張操作を実行する必要があるかどうかに関係なく、ディスクI/O速度に基づいているため、これは非常に困難です。おそらく、最初のテストの変更に11分かかり、2番目のテストがVARCHARNVARCHARデータのサイズの半分であっても、2分しかかからなかった理由の大部分です(つまり、ファイルはその時点で事前に成長しました)。ただし、私のテストは最速のディスクではないラップトップで実行されていますが、2つの小さな列が100万行(行あたり22バイト程度)だったことにも注意してください。

そして、あなたはそれがデータページに何をするかを尋ねたので、ここにあなたの答えがあります。テーブルの作成後、sp_spaceusedの実行後、ALTER COLUMNの実行後にALTER TABLE dbo.ResizeTest REBUILD;を実行しました。結果(以下の数値は、VARCHARを使用した最初のテストではなく、NVARCHARを使用した2番目のテストに基づいています):

After initial table creation:        526,344 KB
After ALTER COLUMN VARCHAR(500):   1,031,688 KB  <--- !! Yikes!!
After ALTER REBUILD:                 526,472 KB

可能な限り最短の時間で操作を維持する必要がある場合は、 1億行(またはそれ以上)のテーブルを秒単位で再構築してください。 SRSLY! (無料登録が必要です)。

12
Solomon Rutzky

私が集めたものから、テーブルが別のプロセスによってロックされていない限り、alterステートメントの実行にはそれほど時間がかかりません。 GBNによると、これはメタデータの変更にすぎません: https://stackoverflow.com/questions/7261909/is-it-bad-to-use-alter-table-to-resize-a-varchar-column-to -a-larger-size

また、格納方法については、SQL Serverがvarcharデータを8kページに格納してページ全体を埋めるようにしたようです。この時点で、ポインターで置き換えられ、BLOBとして格納されます。

長さを変更しても、レコードが切り捨てられることはないと想定しています。その場合、最大でvarchar(500)に変換するデータは、最大で502バイトの長さで、ポインターを含めないでください。

要するに、話は短く、データを切り捨てない限り、それほど変更すべきではありません。

1
DForck42