web-dev-qa-db-ja.com

VarChar(Max)を保存します[注意]同じまたは別のテーブルの列

免責事項

少し前にテーブルデザインのアイデアを思いつきました。最近の歴史の中で、私は「オーバーエンジニアリング」の習慣を持っているか、ソリューションを「オーバーオプティマイズ」しようとすることに時間をかけすぎることに気づきました。これは私が解決策を考えすぎており、実際の利益がほとんどないかまったくない余分なオーバーヘッドが発生する場合の1つであると想定しています。

質問

オブジェクト(たとえば、Shipmenttable)について、追跡したいNOTEvarchar(MAX)データ要素があると仮定します。 NOTEcolumnは、データをオーバーフローにプッシュし、rowのサイズを劇的に増加させる機会があります(したがって、rowsに保存できるpageの数を制限します)。私が理解しているように、これはテーブル全体のさまざまな操作の実行時間に悪影響を及ぼします。

columnShipmentNotetableとして保持する代わりに、columnを別のスタンドアロンShipmenttableにプッシュする必要があるインスタンスはありますか?理論的には、NOTEcolumnを別のtableにプッシュすると、pagesShipmenttableが保存され、Shipmenttableのすべての操作をより効率的に実行できます。 rowサイズが小さくなり、より多くのrowsを同じpageに収まるようになりました。

(以下のスキーマの例を参照してください):

ER Diagram

これが良いアイデアとなる主なユースケースは、次の場合です

  • Notecolumnは通常8000文字を超えています(これは、追加のページングを使い始めたときです)
  • NotecolumnSELECT操作でのみ返され、JOINまたはWHEREの一部として使用されることはほとんどありません
  • columnsの残りのShipmentは、Noteとは関係なく定期的にクエリされます(IE:ほとんどの操作はNoteを利用しません。そのため、JOINまたはWHERE条件が[発送]の他のcolumnsで発生します)

私が目にしている不利な点(これ以外では、実際にShipment列の外のNoteテーブルを操作する際に顕著な改善が見られない場合があります):

  • triggerに常に何らかの種類の値があることを確認することが不可能になった(または少なくともNOTEか何かが必要になる)(IE:現在は別のchild tableにあるため、NOTENOT NULLrow内のすべてのShipment
  • NOTEを使用するすべての操作は、正しいレコードで作業していることを確認するためにJOINを実行する必要があるため、余分な労力がかかるようになります。
3
Kirk Saunders

あなたがこれについてさえ考えていることは素晴らしいことですが、私はそれをミクロ最適化であると考えます。 SQL Serverには、NVARCHAR(MAX)を処理するための最適化がすでに組み込まれているため、一般的に、問題が発生するまで、推測する必要はありません。ただし、質問を読んだときに頭に浮かんだ主な2つのポイントがあります。

1つ目は(最後のポイントで触れたように)、SQL Serverにページとデータ自体を最適化させるよりも、データを別のテーブルに分割することで実際にパフォーマンスが向上するかどうかです。今のところ、確固たる証拠はありませんが、そうではないと思います。その理由は、お伝えしたように、データは通常8000バイトを超えているため、とにかくNoteテーブルのLOBページに移動されるためです。認識された問題を1つのテーブルから別のテーブルに移動するだけです。データをフェッチする必要がある場合にJOINを実行するオーバーヘッドを追加すると、最初よりも少し悪い結果になる可能性があります。

次に、データベースのデザインで質問にタグを付けたとき、私の実際の推奨事項は、あなたがdoノートを別のテーブルに分割することです。ただし、私の推論は、パフォーマンスの最適化ではなく、より具体的にはアプリケーションに柔軟性を追加することに基づいています。貨物に複数のメモを添付する必要がある可能性が高いです(たとえば、輸送中に遅延した場合、または顧客が電話をかけた場合など)。実際の出荷自体に関するメモがある場合、データを複製せずにこれを行うことは困難になります。それを独自のテーブルに抽出すると、出荷に複数のメモを割り当て、誰がいつ入力したかを追跡できます。これにより、アプリケーションとデータベースがより柔軟になります。

最適化したい場合は、誰かが特にそれらを表示したい場合(アプリケーションに専用フォームを用意するなど)を除いて、ノートをクエリする必要をなくすことをお勧めします。そうすれば、誰かが明示的にデータを表示したい場合にのみ、結合/検索を実行する必要があります。ノートを別のテーブルに外部化していなくても、列が不要な場合にクエリに含めないことで、SQL ServerがLOBページを読み取る必要がなくなります。可能であれば、マイクロレベルで最適化する前に、必要な最小限の情報を返すように常にクエリを最適化します。

4
World Wide DBA

単純な答えは「ノー」です。ただし、常にテーブルのすべての列をフェッチするアプリケーションがあり、シップメントを照会するたびにメモが取得されないようにする必要がある場合を除きます。

行にメモを保存しないようにSQL Serverに指示し、テーブルオプション '大きな値の型から行を外す' を使用して別のLOBへのポインターを使用し、プッシュすることもできる場合 CREATE TABLE でTEXTIMAGE_ONオプションを設定して、これらのLOBを別のファイルグループに追加します。