すべての Sql Server 2008 文字列列を varchar(max) にすることに問題はありますか? 許容される文字列サイズはアプリケーションによって管理されます。データベースは、私が与えたものを永続化する必要があります。Sql Server 2008 ですべての文字列列を varchar(max) 型に宣言すると、実際にデータのサイズに関係なく、パフォーマンスが低下しますか?
7 に答える
を使用VARCHAR(MAX)
することで、基本的に SQL Server に「このフィールドに最適な方法で値を格納する」ように指示することになり、SQL Server は値を通常VARCHAR
または LOB (ラージ オブジェクト) として格納するかどうかを選択します。一般に、格納されている値が 8,000 バイト未満の場合、SQL Server は値を通常のVARCHAR
型として扱います。
text
格納された値が大きすぎる場合、他の LOB タイプ ( 、ntext
および) の場合とまったく同じように、列がページから LOB ページに流出することが許可されます。image
これが発生した場合、格納されたデータを読み取るために追加のページ読み取りが必要になります。追加のページ (つまり、パフォーマンスが非常に悪い) ですが、これは格納された値が大きすぎる場合にのみ発生します。
実際、SQL Server 2008 以降では、データは固定長データ型 (例: VARCHAR(3,000)
) でも追加のページにオーバーフローする可能性がありますが、これらのページは行オーバーフロー データ ページと呼ばれ、扱いが若干異なります。
短いバージョン:ストレージの観点からは、VARCHAR(MAX)
overVARCHAR(N)
を使用しても不利な点はありませんN
。
(これは、他の可変長フィールド タイプNVARCHAR
およびにも適用されることに注意してくださいVARBINARY
)
インデックスは、1 つの幅が 900 バイトを超えることはできません。したがって、おそらくインデックスを作成することはできません。データが 900 バイト未満の場合は、varchar(900) を使用します。
これは 1 つの欠点です。
- 検索性能がかなり悪い
- 一意の制約なし
サイモン・セイビンは、これについて少し前に投稿を書きました。今はそれを取得する時間はありませんが、デフォルトで 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文字以上が必要な場合は、必ず...それを使用してください.
この質問については、具体的には言及されていないいくつかの点があります。
- 2005/2008/2008 R2 では、インデックスに LOB 列が含まれていると、オンライン インデックスの再構築がブロックされます。
- 2012 では、オンライン インデックスの再構築の制限は解除されましたが、LOB 列は新しい機能の オンライン操作としての NOT NULL 列の追加に参加できません。
- このデータ型の列を含む行では、ロックをより長く解除できます。(もっと)
なぜvarchar(8000)
どこにでもないのかについての私の答えには、他のいくつかの理由が含まれています。
- クエリは、データのサイズによって正当化されない巨大なメモリ許可を要求することになる場合があります。
- トリガーのあるテーブルでは、バージョン管理タグが追加されていない最適化を妨げる可能性があります。
以前、同様の質問をしました。興味深い回答を得ました。ここでチェックしてください 幅の広い列を使用することの不利益について話している人がいるサイトが1つありましたが、アプリケーションでデータが制限されている場合、私のテストではそれが反証されました. 列にインデックスを作成できないということは、私がそれらを常に使用するわけではないということです (個人的にはあまり使用しませんが、その点では少し純粋主義者です)。ただし、あまり保存されていないことがわかっている場合は、それほど悪くはないと思います。varchar(max) を含むレコードセット (または char または varchar である幅の広い列) で列を並べ替えると、パフォーマンスが低下する可能性があります。これらは (必要に応じて) インデックスによって解決できますが、varchar(max) にインデックスを配置することはできません。列を将来的に証明したい場合は、それらを合理的なものにしてみませんか。たとえば、名前列は最大ではなく 255 文字です...
すべての列で varchar(max) を使用しないようにする別の理由があります。チェック制約を使用するのと同じ理由で (誤ったソフトウェアやユーザー エントリによってテーブルがジャンクでいっぱいになるのを避けるため)、意図したよりもはるかに多くのデータを追加する欠陥のあるプロセスから保護する必要があります。たとえば、誰かまたは何かが City フィールドに 3,000 バイトを追加しようとした場合、何かが間違っていることが確実にわかり、可能な限り早い時点でデバッグするためにプロセスの停止を望むでしょう。また、3000 バイトの都市名は有効ではない可能性があり、それを使用しようとするとレポートなどが台無しになることもわかっています。
理想的には、必要なものだけを許可する必要があります。つまり、特定の列 (ユーザー名の列など) が 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 バイトに近づくことは本当にありますか?