web-dev-qa-db-ja.com

varchar(max)どこでも?

すべてのSql Server 2008文字列列をvarchar(max)にすることに問題はありますか?許容される文字列サイズは、アプリケーションによって管理されています。データベースは、私が与えたものをそのまま保持する必要があります。 SQL Server 2008では、実際に入力されるデータのサイズに関係なく、すべての文字列列をvarchar(max)型として宣言することでパフォーマンスが低下しますか?

77
BowserKingKoopa

VARCHAR(MAX)を使用することにより、基本的にSQL Serverに「このフィールドに値を最適に表示する方法を保存する」と伝え、SQL Serverは通常のVARCHARまたはLOB(ラージオブジェクト)として値を保存するかどうかを選択します)。 一般に、格納されている値が8,000バイト未満の場合、SQL Serverは値を通常のVARCHARタイプとして扱います。

格納されている値が大きすぎる場合、他のLOBタイプ(textntextおよびimage)の場合とまったく同じように、列はページからLOBページにあふれることができます。これが発生した場合、追加ページに格納されたデータを読み取るために追加のページ読み取りが必要です(つまり、パフォーマンスが低下します)。ただし、これは格納された値が大きすぎる.

実際、SQL Server 2008以降では、データは固定長のデータ型(例:VARCHAR(3,000))でも追加ページにオーバーフローする可能性がありますが、これらのページは行オーバーフローデータページと呼ばれ、少し異なる方法で処理されます。

ショートバージョン:ストレージの観点から、いくつかのNに対してVARCHAR(MAX)よりもVARCHAR(N)を使用することのデメリットはありません。

(他の可変長フィールドタイプNVARCHARおよびVARBINARYにも適用されることに注意してください)

参考-あなた VARCHAR(MAX)列にインデックスを作成できません

46
Justin

1つのインデックスは900バイトを超えることはできません。したがって、おそらくインデックスを作成することはできません。データが900バイト未満の場合は、varchar(900)を使用します。

これは1つの欠点です。

  • 本当に悪い検索パフォーマンス
  • 一意の制約はありません
32
gbn

サイモン・サビンは、しばらく前にこれに関する投稿を書きました。私は今それをつかむ時間がありませんが、デフォルトでvarchar(max)を使用するべきではないという結論に達するので、検索する必要があります。

編集:Simonがvarchar(max)に関するいくつかの投稿を受け取りました。以下のコメント内のリンクは、これを非常にうまく示しています。最も重要なのは http://sqlblogcasts.com/blogs/simons/archive/2009/07/11/String-concatenation-with-max-types-stops-plan-caching.aspx =、これはプランキャッシングに対するvarchar(max)の効果について説明しています。一般的な原則は注意することです。最大値にする必要がない場合は、最大値を使用しないでください。8000文字を超える文字が必要な場合は、それを確認してください。

9
Rob Farley

この質問については、特に言及されていないいくつかのポイントがあります。

  1. 2005/2008/2008 R2では、LOB列がインデックスに含まれている場合、オンラインインデックスの再構築がブロックされます。
  2. 2012年には、オンラインインデックス再構築の制限が解除されますが、LOB列は新しい機能に参加できません オンライン操作としてNOT NULL列を追加
  3. このデータ型の列を含む行では、ロックをより長く解除できます。 ( 詳細

なぜvarchar(8000) everywhereではない に関する他のいくつかの理由が私の答えでカバーされています。

  1. クエリは、データのサイズによって正当化されない巨大なメモリ許可を要求することになります。
  2. トリガーのあるテーブルでは、バージョン管理タグが追加されていない最適化を防ぐことができます。
5
Martin Smith

先ほど同様の質問をしました。興味深い返信がありました。それを確認してください here 幅の広い列を使用することの不利益について話している人がいたサイトが1つありましたが、アプリケーションでデータが制限されている場合、私のテストはそれを反証しました。列にインデックスを作成できないという事実は、私は常にインデックスを使用しないことを意味します(個人的にはあまり使用しませんが、その点では少し純粋主義者です)。しかし、あなたがそれらにあまり格納されていないことを知っているなら、私はそれらがそれほど悪いとは思わない。 varchar(max)を含むレコードセットの列(またはcharまたはvarcharである幅の広い列)で並べ替えを行うと、パフォーマンスが低下する可能性があります。これらは(必要に応じて)インデックスによって解決できますが、varchar(max)にインデックスを置くことはできません。将来的にカラムを校正したい場合は、単に合理的なものに入れてみてください。たとえば、名前列はmax ...ではなく255文字です。

4
AtaLoss

すべての列でvarchar(max)を使用しないようにする別の理由があります。同じ理由で、チェック制約を使用して(誤ったソフトウェアやユーザーエントリによって発生する迷惑メールでテーブルがいっぱいにならないように)、意図したよりも多くのデータを追加する障害のあるプロセスから保護したいと思います。たとえば、誰かまたは何かがCityフィールドに3,000バイトを追加しようとした場合、何かが間違っていることが確実にわかり、可能な限り早い段階でデバッグするためにそのプロセスで停止しているプロセスを停止する必要があります。また、3000バイトの都市名は有効ではない可能性があり、使用しようとするとレポートなどが台無しになることもわかっています。

1
Larry Ness

理想的には、必要なものだけを許可する必要があります。特定の列(ユーザー名列など)の長さが20文字を超えないことが確実な場合、VARCHAR(20)とVARCHAR(MAX)を使用すると、データベースでクエリとデータ構造を最適化できます。

MSDNから: http://msdn.Microsoft.com/en-us/library/ms176089.aspx

Variable-length, non-Unicode character data. n can be a value from 1 through 8,000. max indicates that the maximum storage size is 2^31-1 bytes.

これらの列で実際に2 ^ 31-1バイトに近づいていますか?

1
leepowers