DELETE
ステートメントがフルテキストインデックス列のあるテーブルに対して実行されていますが、cascade
が有効になっている少数の外部キーがあります。次のようになります。
DELETE FROM dbo.STUDENTS WHERE STUDENTID=@STUDENTID
DELETE
に非常に長い時間がかかり、ロックが発生するように、すべてのインデックス操作の非常に高い行推定を含む計画がコンパイルされる場合があります。
QueryStoreで適切なプランを強制しようとしましたが、これは実際には機能せず、last forced plan failure description
/NO_PLAN
を示しています。
計画を無効にする可能性のあるスキーマの変更がないことを確認しました。
実行プランを見ると、DELETE
にはFTインデックスを保持するシステムテーブルへの結合が含まれていることがわかります。
このFTインデックスへの結合は、プラン強制がサポートされていないことを意味しますか?
計画強制の制限 を見ると、箇条書きの1つは次のとおりです。
分散クエリまたは全文操作
ただし、この制限は削除が計画の強制に失敗することを意味しません。
SELECT
列にフルテキストインデックスが設定されているテーブルで、次の4つのクエリ、2つのDELETE
ステートメントと2つのval
ステートメントを考えてみます。
_SELECT *
FROM dbo.fulltextindexed;
SELECT val
FROM dbo.fulltextindexed
WHERE CONTAINS(val, N'WOW');
DELETE top(1)
FROM dbo.fulltextindexed;
DELETE top(1)
FROM dbo.fulltextindexed
WHERE id <500 and id > -1;
_
失敗している唯一のクエリは、2番目のクエリで、CONTAINS
ステートメントを使用しています。
失敗の理由は_DQ_NO_FORCING_SUPPORTED
_です。
同じ_clustered index merge
_演算子も示す2つの削除ステートメントの計画が強制されます。
このソース は_DQ_NO_FORCING_SUPPORTED
_に関する詳細情報を提供します:
分散クエリまたはフルテキスト操作の使用とプランが競合するため、クエリを実行できません
質問に答えるために
このFTインデックスへの結合は、プラン強制がサポートされていないことを意味しますか?
_DQ_NO_FORCING_SUPPORTED
_エラーではなく_NO_PLAN
_エラーが表示されるため、これは理由ではないというのが私の答えです。理由は、プランを無効にする別の制限、インデックスの変更、追加された外部キーなどが原因である可能性があります。
追加テスト
テーブルを追加し、上記のクエリで使用されるテーブルを参照するon deleteカスケードで外部キーを作成する場合、強制プランを使用できなくなるため、削除は失敗することが予想されます。
_CREATE TABLE dbo.fulltexreference(id int identity(1,1) primary key not null, t1id int, val varchar(max));
ALTER TABLE dbo.fulltexreference add constraint FK_test foreign key(t1id) REFERENCES dbo.fulltextindexed(id) ON DELETE CASCADE;
_
予想通り、2つの削除ステートメントで_NO_PLAN
_を取得します
計画を強制することは私たちに救いを与えます:
_NO_PLAN
_の問題を削除します
削除クエリが実行されているメインテーブルを参照する外部キー(on deleteカスケード付き)を持つフルテキストインデックスを持つテーブルにも同じことが当てはまります。
高い/低い見積もりについて
削除がそれほど実行されない場合、OPTION(RECOMPILE)
を追加すると、実行時に変数が「見える」ため、オプティマイザがより適切な推定を行うことができるため、高い行推定に役立ちます。
クエリプランで別の質問を投稿すると、別の回避策/ソリューションが表示される場合があります。