フィルタリングされたインデックスの使用を強制しようとしている問題
-
28-09-2020 - |
質問
私は昨日フィルタリングされた索引をテストしようとしていて、かなり簡単な状況を作成しました:
CREATE TABLE IndexTest
(
ID INT NOT NULL IDENTITY(1,1) CONSTRAINT pk_IndexTest PRIMARY KEY,
Col1 CHAR(1)
)
GO
CREATE INDEX ix_IndexTest ON IndexTest(Col1)
WHERE Col1 IS NOT NULL
GO
INSERT INTO IndexTest VALUES ('A'),('B'),('C'),('D')
INSERT INTO IndexTest VALUES (''),(''),(''),('')
INSERT INTO IndexTest VALUES (NULL),(NULL),(NULL),(NULL)
GO
.
次に、ヒントを使用して次のクエリを実行してフィルタリングされたインデックスを使用するように強制します。
SELECT *
FROM IndexTest WITH (INDEX(ix_IndexTest))
GO
.
しかし私はエラーを得る続けています:
クエリプロセッサは、このクエリで定義されているヒントのためにクエリプランを生成できませんでした。ヒントを指定せずに、Set ForcePlanを使用せずにクエリを再実行依頼してください。
フィルタを取り外すがそれとは機能しない場合は機能します。 WHERE Col1 = ''
などのさまざまな方法でフィルタを変更しようとしました。フィルタがある場合はいつでもそのエラーが発生します。誰かがなぜ私に言うことができますか?私は間違ったことをしていますか?
SQL Server 2012および2014インスタンスでこれを試してみて、ここでSQLFIDDLEを作成しました:
解決
場合によっては、フィルタリングされたインデックスが自動的に結果をフィルタすることはないことです。インデックスを使用できるようにするために、インデックスのフィルタ述語と一致するWHERE句を作成する必要があります。
つまりROWS WHERE Col1 IS NOT NULL
を取得しようとしている場合は、行を制限するためのWHERE
句が必要です。 SQL Serverが、テーブルよりも少ない(または同じ*)行を保持しているインデックスの定義では、照会によって返されるすべての行を満たすことを強制しようとしているインデックスを使用できない場合は、実行できません。
*
これが機能する場所をテストしていないシナリオがあるかもしれません。たとえば、列がNOT NULL
(またはすべての行がフィルタ述語に一致するようになる)に制約されている場合、フィルタリングされたインデックスは拡張によって、テーブル全体から行を表します。しかし、それはかなり物議的で非実用的なシナリオです(それが働くことになっていたとしても)。また、単一の挿入または更新が破損する可能性があるため、SQL Serverは現在すべての行が現在フィルタと一致している場合の計画を生成できませんでした。
基礎となるテーブル/ CIが破損しているため、クラスタ化されていないインデックスからデータを見つけようとしている場合は、おそらくDBCC IND/PAGE
またはHex-Editor-Wielding Paul Randalの偽装を伴うことがおそらく、おそらく運が良くなるでしょう。