時間がかかる削除クエリがあります。実行プランを見ると、削除クエリの推定コストのほとんどは、データモデルの、大量のデータ(たとえば、40万行)に問題がないように見えるセクションにありますが、1つのことを理解できません。
データモデルのストリップビュー:
table ParentObject
int parentObjectId (PK)
table Child
int childId (PK)
int parentId (FK)
<stuff>
table GrandChild
int grandChildId (PK)
int childId (FK)
<more stuff>
親オブジェクトに200,000の子があり、子に2つほどのGrandChildrenがある場合。以下のパフォーマンスの調整に興味があります。
DELETE FROM ParentObject WHERE parentObjectId = %d;
孫では、(childId、+ 2つの列)に追加の非クラスター化インデックスと主キーインデックスがあります。子には、追加の非クラスター化一意インデックスがあります(parentId、+ 2つの列)。
クエリプランで見たのは、孫オブジェクトの削除中に、2つの高価な並べ替え操作が削除と混在していたため、なぜそれらが存在するのか理解できません。
この削除操作を高速化するために何を見るべきですか?並べ替える必要がありますか? IDを非正規化し、親IDを孫テーブルに追加した場合、役に立ちますか?私は愚かに私のインデックスを構築しましたか?
主な質問に直接答えるために、ソートは、インデックスキーの順序で演算子を更新する(この場合は削除を実行する)行を表示するためにあります。ここで機能する原則は、キーでのソートにより、インデックスへの順次アクセスが促進されることです。
詳細はハードウェア、影響を受けるページがメモリにある可能性、およびそれらに割り当てられたメモリ内でソートが完了するかどうかによって異なりますが、これは適切な最適化になります。オプティマイザが、順次インデックスアクセスに関連する効率の向上によってソートのコストが返済されると判断すると、更新演算子にプロパティDMLRequestSort
を設定します。
オプティマイザーは、クラスター化インデックス(またはヒープ)を維持するために更新を個別のオペレーターに分割し、非クラスター化インデックスを維持することも決定します。多くの場合、最初にクラスター化インデックスキーに対して、次に再度非クラスター化インデックスに対して、複数回ソートすることを決定します。繰り返しになりますが、ソートが最適であると見なされる場合、各インデックス更新演算子はDMLRequestSort
プロパティをtrueに設定します。
つまり、最初に修正することは、フィードする結合演算子がネストされたループ結合であるインデックススキャンを排除し、熱心なインデックススプールを削除します。これは、クエリが実行されるたびに 空のインデックスに行を挿入する です。多くの場合、熱心なインデックススプールは、有用な永続インデックスがないことを示す最も明確な兆候です。インデックススプールオペレータのシーク述語は、オプティマイザがインデックスを要求するキーを識別します。
非クラスター化インデックスが欠落している(熱心なインデックススプールが必要)テーブルの例は次のとおりです。
child6gc8Selections
gc9s
child7s
gc6s
ネストされたループ結合の下で現在スキャンされているテーブルの例は次のとおりです。
child1
parentObjectMessages
child8s
child7s
child6s
child5s
child4s
child3s
child2s
上記の例では、クラスター化インデックススキャンの出力リストはId, parentObjectId
、入れ子ループ結合述語はchild7s.parentObjectId = parentObject.Id
、結合出力列リストはchild7s.Id
です。
その情報から、クエリのこの部分のchild7s
に対する適切なアクセス方法(インデックス)は、parentObjectId
をキーとして、Id
をインクルード列として指定することになります。これを既存のインデックス作成戦略に組み込むための最善の方法を理解できるはずです。
以下は、オプティマイザが現在ハッシュ結合を選択しているテーブルの例です。このようなテーブルをチェックして、それが適切なアクセス方法であることを確認します。
child6gc8Selections
gc2s
gc5s
gc6Properties
テーブルchild2bigChild
は、明示的なソートが必要なマージ結合にも参加しています。繰り返しますが、この種の問題を回避できるかどうかを確認します。
基本的なインデックス作成の問題が解決したら、必要に応じて他の最適化を確認できます。