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


22

彼らが見たとき、誰かが私が使用して見て、提案されたテーブルを作成するための私のDDLコードをレビューしてたVARCHAR(256)私がすべきことを、私は最初の名前または何のような、かなり小さいことが予想されるテキストのフィールドを常にだけ使用VARCHAR(MAX)し、リンクを使用する理由は何もなく、varchar型(最大)。私はそれを読みましたが、2005年に焦点を当てていたため、日付があり、すべてのテキストフィールドで1行あたり最大2GBを割り当てる可能性を実際に正当化するようには思われませんでした。

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

回答:


31

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

いや

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

物理ストレージは、列は次のようにタイプされているかどうか、同一であるvarchar(n)か、varchar(max)それが問題ではないので、。

どこでも選択しない理由(n)varchar(max)は、機能、計画品質、およびパフォーマンスに関係しています。

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

特徴

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

性能

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

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

コンテキスト内の各型を評価し、正しい基本型(varcharまたはnvarchar)と適切な明示的な長さを使用します。

参考文献:


8

これは妄想の答えのように読みますが、ストレージとパフォーマンスの考慮事項だけではありません。

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

私はこれを行う方法を正確には知りませんが、すべてのテキストフィールドを作成することによりvarchar(max)、クライアントにボビーテーブルの問題があり、および/またはストアドプロシージャのパラメータもあるvarchar(max)場合、攻撃者が簡単に思い付くことができますクライアントが実行するはずのないことを実行できる、有効であるが巧妙なパラメータ値-それが何であれ。

あなたは何に長さ制限することにより、実際に必要とし、あなたがいないシールド "(私も必ず実際に、私はちょうどそれしばらく前に読ん覚えているというものではないよ)これらの巧妙な攻撃から身を、しかし、あなたは言っていません実行するには、2GBのスクリプトを実行してください」


おそらく「インジェクション」(より具体的には「SQLインジェクション」)と呼ばれます。
アンドリーM

@AndriyMええ、何らかの理由でSQL切り捨て攻撃を考えていました(MSはブックマークしたリンクを削除したようです)が、それは基本的にvarchar(not-max)パラメータを悪用しているので、ここでちょっと足を止めました。ただし、SQLインジェクションはここで適用できます。おそらく、この答えを少し言い換えるべきでしょう。
マチューギンドン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.