web-dev-qa-db-ja.com

単純なDELETEですが、複雑な実行プラン

この削除を実行すると:

DELETE FROM ETLHeaders WHERE ETLHeaderID < 32465870

... 39,157行を削除します。クラスター化されたインデックスと主キーであるETLHeaderIDを削除しているので、単純なはずです。しかし、(実行計画によると)361,190行に達し、他のインデックスを使用しているようです。テーブルには、XMLデータ型のフィールドがあります(このDELETEに影響する場合)。

なぜ、どのように私はこのDELETEを高速化できるのでしょうか?

ここの実行計画: http://sharetext.org/qwDY ここのテーブルスキーマ: http://sharetext.org/Vl9j

ありがとう

9
Craig HB

計画の最上位レベルは、ベーステーブル(クラスター化インデックス)から行を削除し、4つの非クラスター化インデックスを維持することに関係しています。これらのインデックスのうち2つは、クラスター化インデックスの削除が処理されるときに、行ごとに維持されます。これらは、以下の緑色で強調表示されている「+2非クラスター化インデックス」です。

他の2つの非クラスター化インデックスについては、オプティマイザーはこれらのインデックスのキーをtempdb作業テーブル(Eagerスプール)に保存し、次にスプールを2回再生して、インデックスキーで並べ替え、シーケンシャルアクセスパターンを促進するのが最善であると判断しました。

Regular index maintenance

操作の最後のシーケンスは、DDLスクリプトに含まれていないプライマリおよびセカンダリxmlインデックスの維持に関係しています。

XML index maintenance

これについて行うことはあまりありません。非クラスター化インデックスとxmlインデックスは、ベーステーブルのデータと常に同期している必要があります。そのようなインデックスを維持するコストは、テーブルに追加のインデックスを作成するときに行うトレードオフの一部です。

とはいえ、xmlインデックスは特に問題があります。この状況でオプティマイザが適格な行数を正確に評価することは非常に困難です。実際、これはxmlインデックスを大幅に過大評価しているため、このクエリには約12GBのメモリが許可されています(ただし、実行時に使用されるのは28MBのみです)。

Estimated row counts

過度のメモリ許可の影響を減らすことを期待して、小さなバッチで削除を実行することを検討できます。

また、OPTION (QUERYTRACEON 8795)を使用して、並べ替えなしで計画のパフォーマンスをtestすることもできます。これは ドキュメントに記載されていないトレースフラグ なので、本番環境では決して開発またはテストシステムでのみ試してください。結果のプランがはるかに高速である場合は、プランXMLをキャプチャして、プロダクションクエリの プランガイドの作成 に使用できます。

10
Paul White 9

順調です。XMLインデックスが問題です。明らかに、プライマリXMLインデックスとセカンダリXMLインデックスがあります。

ベーステーブル(ETLHeaders)に対してDELETEを実行する場合、このテーブルのすべてのインデックスからもデータを削除する必要があります。このオーバーヘッドは、特にXMLインデックスの場合に重大になる可能性があります。

長い期間を引き起こしているインデックスは、セカンダリXMLインデックス[XML_IX_ETLHeaders_Property]です。 「リレーショナルテーブル」の39,157行は、プライマリXMLインデックス[XML_IX_ETLHeaders]の361,190行を参照します。セカンダリインデックスの削除に使用できるようにするには、これらの361k行を並べ替える必要があります。そして、この並べ替え操作はクエリの長​​い期間を引き起こしています。 (付記として、両方のxmlインデックスのインデックス統計はかなりずれているようです:プライマリxmlインデックスの361k行の実際のデータサイズは160MBですが、推定データサイズはほぼ4TBです(そう、4テラバイト!!)) 。

このクエリを高速化する唯一の選択肢は、セカンダリXMLインデックスを削除することです。データによっては、XMLデータをリレーショナルテーブルに細断する方が適切な場合があります。

3
Lmu92