web-dev-qa-db-ja.com

MAXテキストまたはより具体的で小さいタイプの使用

誰かがテーブルを作成するために私のDDLコードをレビューし、提案しました。彼らがテキストのVARCHAR(256)フィールドの使用を見て、私がするべきファーストネームなどのかなり小さいと予想されるalwaysVARCHAR(MAX)を使用してリンクする なぜvarchar(max)以外のものを使用する 。私はそれを読みましたが、2005年に焦点を合わせていたため、日付が付けられているようで、すべてのテキストフィールドで行あたり最大2 GBを割り当てる可能性があるという正当な理由はありませんでした。

パフォーマンス、ストレージなどの観点から、SQL Serverの最新バージョンにVARCHAR(MAX)を使用するか、より具体的なタイプを使用するかを決定するにはどうすればよいですか? (例:2008、2012、2014)

22
Phrancis

テキスト列には常に_(n)varchar(max)_を使用する必要がありますか?

いいえ

SQL Serverの場合、maxデータ型は、代替がない場合にのみ指定する必要があります。代わりに、正しい基本タイプ(varcharまたはnvarchar)を選択し、格納するデータに適切な最大長を明示的に指定する必要があります。

物理ストレージは、列がvarchar(n)varchar(max)のどちらとして入力されても同じなので、これは問題ではありません。

機能、計画の品質、およびパフォーマンスを中心に展開するすべての場所で_(n)varchar(max)_をしないにする理由.

完全なリストはおそらく実用的ではありませんが、とりわけmax列:

特徴

  • 最大長を強制するには、別の制約が必要です
  • インデックスのキーにすることはできません(したがって一意制約もありません)
  • オンラインDDL(インデックスの再構築と新しいnull以外の列の追加を含む)を妨げる可能性があります
  • 通常、「新しい」機能ではサポートされていません。列ストア
  • より具体的な機能と制限については、製品のドキュメントを参照してください。一般的なパターンでは、maxデータ型の周りに厄介な制限と制限があります。すべての制限と副作用が文書化されているわけではありません。

パフォーマンス

  • 非常に大きなサイズになる可能性があるため、実行エンジンで特別な処理が必要です。通常、これには、ストリーミングインターフェイスで効率の悪いコードパスを使用することが含まれます。
  • 外部コード(およびSSISなどの他のSQL Serverコンポーネント)にも同様の予期しない結果が生じる可能性があります。これは、最大2GBのデータを処理するために準備する必要もあります
  • メモリ許可の計算では、4000バイト幅であると想定されます。これにより、過度のメモリ予約が発生し、同時実行性が制限され、貴重なインデックスとデータページがキャッシュメモリから押し出されます。
  • いくつかの重要なパフォーマンス最適化を無効にする
  • ロック期間を延長する可能性があります
  • オプティマイザが(非動的)シーク計画を選択できない可能性があります
  • フィルターがスキャンにプッシュされないようにし、残差としてシークします
  • Tempdbの圧力と競合が増える可能性があります(バージョンに依存)。変数とパラメーターも列定義と一致するようにmaxと入力される可能性が高いためです

要約すると、max指定子を不必要に使用すると、微妙な(そして望ましくない)副作用がたくさんあるため、これを行う意味がありません。単一の宣言を使用することのマイナーな「便利さ」は、一種の補償ではありません。

コンテキストで各タイプを評価し、正しい基本タイプ(varcharまたはnvarchar)、および適切な明示的な長さを使用します。

参考文献:

31
Paul White 9

これは偏執狂の答えのように読むつもりですが、のみストレージとパフォーマンスの考慮事項はありません。

Entity Frameworkを使用してトランザクションをカプセル化し、パラメーター化されたクエリを保証する.netアプリケーションでのみデータベースが使用されるように設計されている場合でも、データベース自体はクライアントを制御せず、クライアントは常にユーザー入力を安全に挿入するとは限りません体系的に使用されている場合は、知っているを常に使用することはできません。

私はこれを正確に行う方法がわかりませんが、すべてのテキストフィールドをvarchar(max)にすることで、クライアントにBobby Tablesの問題があるか、ストアドプロシージャのパラメータもvarchar(max)を使用すると、攻撃者が、クライアントが実行してはならないことを実行できる、有効でありながら悪意のあるパラメーター値を簡単に見つけられるようになります。

長さをあなたが実際に必要なものに制限することによって、あなたはこれらの巧妙な攻撃からshielding自分自身ではありません(私はそれが実際に何と呼ばれるかさえわかりません、私はただ読んだことを覚えていますしばらく前からですが)、「先に進み、2GBのスクリプトを実行してみてください」とも言っていません。

8
Mathieu Guindon