どこでもvarchar(max)?


81

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


1
私の読書では、SQLServerのvarchar列の「自動サイズ設定」自体のように聞こえます。したがって、任意の値の最大長が20であるvarchar(max)列は、varchar(20)列と同じではないでしょうか。
BowserKingKoopa 2010年

回答:


49

VARCHAR(MAX)基本的にSQLServerに「このフィールドに最もよく見える方法で値を格納する」ように指示することにより、SQL Serverは値を通常として格納するかVARCHARLOB(ラージオブジェクト)として格納するかを選択します。一般に、格納されている値が8,000バイト未満の場合、SQLServerは値を通常のVARCHAR型として扱います。

格納された値が大きすぎるその後、カラムは、彼らが他のLOB型のために行うとおりに、LOBページへのページをオフにこぼさ許可(されている場合はtextntextimage) -これは、その後発生した場合、追加のページが読み込みに格納されたデータを読み出すために必要とされています追加のページ(つまり、パフォーマンスが低下する)。ただし、これは、格納されている値が大きすぎる場合にのみ発生します

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

短いバージョン:ストレージの観点から、いくつかのに使用VARCHAR(MAX)することの不利な点はありません。VARCHAR(N)N

(これはまた、他の可変長フィールドタイプに適用されますNVARCHARVARBINARY

参考までに-列にインデックスを作成することはできませんVARCHAR(MAX)


これは、NULL可能フィールドにのみ当てはまる可能性があります。null以外の各varchar(max)またはnvarchar(max)列には、24バイトの追加の固定割り当てが必要です。 docs.microsoft.com/en-us/sql/t-sql/data-types/...
Liazy

34

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

これは1つの欠点です:それが与えるので

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

しかし、varchar(max)列に900バイトを超える値がない場合はどうなりますか?それではインデックスを作成しますか?私が読んでいるものの多くは、varchar列タイプが、データが入力されるときに最大値まで自動サイズ設定されているように聞こえるので、混乱しています。データベースではなく、最大値を決定するのはアプリケーションであるため、これは私が望むものに最適です。
BowserKingKoopa 2010年

3
インデックスを作成すると警告が表示され、900を超えるデータを挿入しようとするとエラーが発生します。ただし、データが常に900未満の場合は、900を使用しないのはなぜですか。はい、可変長の文字列として保存されます。
gbn 2010年

8
データが常に900未満であるかどうかはわかりません。これは、ビジネスロジックの問題です。そのルールが変更された場合は、ビジネスロジックで変更する必要があります。データベースも変更する必要はありません。とにかくそれが私の目標です。パフォーマンスに目立った影響を与えることなく、データベースから文字列サイズに関する懸念を取り除くことができるかどうかを確認します。
BowserKingKoopa 2010年

2
長いテキスト列にインデックスを付けることはどのくらいの頻度で役立ちますか?varchar(200)列のようなものにインデックスを付ける価値さえありますか?結局のところ、インデックス自体は非効率的です。長い「完全一致」を検索する必要はないようです。また、パターン検索は、パターンの開始がわかっている場合にのみメリットがあります。
幻滅した2014

9

Simon Sabinは、しばらく前にこれについて投稿しました。今はそれを取得する時間がありませんが、デフォルトで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)の影響。一般的な原則は注意することです。maxにする必要がない場合は、maxを使用しないでください。8000文字を超える必要がある場合は、必ず...それを選択してください。




最初の1つ。OMGポニーによる。
ロブファーリー2010年

申し訳ありませんが、実際のリンクを見つける時間がありませんでした。答えを出したいときに、会議に足を踏み入れようとしていました。
ロブファーリー2010年

1
そしてもっと重要なことに、これは:sqlblogcasts.com/blogs/simons/archive/2009/07/11/…–
Rob Farley

6

この質問については、特に私が言及していないいくつかの点について説明します。

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

他のいくつかの理由は、なぜvarchar(8000)どこにでもない理由についての私の答えでカバーされてます

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

5

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


2

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


1

理想的には、必要なものだけを許可する必要があります。つまり、特定の列(たとえば、ユーザー名列)が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バイトに近づくことはありますか?


3
これを「割り当て」として特徴付けることは正確ではないと思います。DBは確かに実際にはどこにも2 ^ 31-1バイトを予約していません。
スコットスタッフォード

1
「ユーザー名の列[..]が20文字を超えることはありません」-ある日、顧客がもっと長くする必要があると判断するまでは問題ありません。私たちは皆そこにいました。:)
スティーブスミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.