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


15

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

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

前もって感謝します!

編集:

見ているテーブルは20個ありますが、行カウントが1,000を超えるテーブルは半分しかありません。最大のものにはほぼ100万行あります。最悪の違反者は、350,000行と4 VARCHAR(MAX)列からなるテーブルで、このVARCHAR(500)レベルまで縮小できます。

回答:


12

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

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

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

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

他のテストからINT NOT NULL、1 つのフィールドと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]テーブルを削除し、両方NVARCHARの値をVARCHARリンゴを少なくともリンゴのように見えるものと比較していることを確認します;-)。

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

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

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

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

操作を可能な限り最短時間に維持する必要がある場合は、それを行うことについて書いた記事を参照してください。SRSLY!(無料登録が必要です)。


2
そこで、最悪のテーブルをローカルインスタンスにコピーしました(つまり、低速のディスクと1/3のコア)。私はALTER連続して各列を編-各アクションは少ない秒以上かかりました。それらが完了するまでに、テーブルのサイズは2倍になりましたが、一度実行するとREBUILD(これも1秒未満の操作でした)、テーブルは元のサイズに戻りました。
ナテイルビン

@nateirvinそれは聞いてうれしいです。ALTER TABLEすべてのフィールドを一度に実行し、各列をコンマで区切ることで、おそらく操作を高速化できます。トランザクションが大きすぎる場合、テーブルをそれぞれ半分の列の2つのALTERステートメントに分割します。また、テーブルのサイズに応じて、2つのALTERステートメントのそれぞれの間でリビルドを行うこともできます。遊ぶもの。また、テーブルへのすべてのアクセスをブロックする期間、操作はおそらくスキーマロックを取得することに注意してください。
ソロモンラツキー

1
それぞれALTERのサイズの変化を追跡できるようにそれぞれを個別に行いましたが、間違いなく知っておくと良いでしょう。ありがとう!
ナテイルビン

1

私が収集したものから、テーブルが別のプロセスによってロックされていない限り、alterステートメントの実行にそれほど時間がかからないはずです。gbnによると、それは単なるメタデータの変更です。 https -サイズ

また、保存方法については、SQL Serverがページ全体を埋めるまで8kページにvarcharデータを保存したようです。この時点で、ポインタはそれをBLOBとして保存します。

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

つまり、長い話は短く、データを切り捨てない限り、あまり変化しないはずです。


5
これは絶対に間違っています。実際にテストしたので(これは一部の人よりも多いので、それを行ってくれてありがとう)、私はダウン投票しませんが、これを大規模にテストする必要があります。リンクした答えは、サイズを小さくするのではなく、サイズを大きくすることでした。これらは非常に異なる2つの操作です。
ソロモンラツキー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.