次のようなテーブル定義があるとします。
CREATE TABLE MyTab (
ID INT IDENTITY(1,1) CONSTRAINT PK_MyTab_ID PRIMARY KEY
,GroupByColumn NVARCHAR(10) NOT NULL
,WhereColumn DATETIME NULL
)
そして、次のようなフィルターされた非クラスター化インデックス:
CREATE NONCLUSTERED INDEX IX_MyTab_GroupByColumn ON MyTab
(GroupByColumn)
WHERE (WhereColumn IS NULL)
このインデックスがこのクエリに対して「カバー」しない理由:
SELECT
GroupByColumn
,COUNT(*)
FROM MyTab
WHERE WhereColumn IS NULL
GROUP BY GroupByColumn
私はこの実行計画を取得しています:
KeyLookupは、WhereColumn IS NULL述語用です。
これが計画です: https://www.brentozar.com/pastetheplan/?id=SJcbLHxO7
このインデックスがこのクエリに対して「カバー」しない理由:
正当な理由はありません。それがそのクエリのカバーするインデックスです。
こちらのフィードバックアイテムに投票してください: https://feedback.Azure.com/forums/908035-sql-server/suggestions/32896348-filtered-index-not-used-when-is-null-and- key-look
そして workaround として、フィルターされたインデックスにWhereColumn
を含めます:
CREATE NONCLUSTERED INDEX IX_MyTab_GroupByColumn
ON MyTab (GroupByColumn) include (WhereColumn)
WHERE (WhereColumn IS NULL)
数週間前にいくつかのテストを行ったときに私は同じ問題を抱えていました。返される結果にNULLのcloseatetimeが必要なプライマリ述語のクエリがあります。2M+レコードの25KはNULLであり、この数値はすぐに減少するため、フィルター選択されたインデックスを使用することを考えました。
フィルターされたインデックスは使用されませんでした-「非一意性」または共通性が原因であると想定しました Microsoftサポート記事 が見つかるまで:
この問題を解決するには、NULLとしてテストされる列を返される列に含めます。または、この列を索引の組み込み列として追加します。
したがって、列をインデックス(またはインクルード)に追加することは、MSの正式な回答のようです。