次のようなテーブルがあるとします。
create table #data (ID int identity(1, 1) not NULL, Value int)
それにいくつかのデータを入れます:
insert into #data (Value)
select top (1000000) case when (row_number() over (order by @@spid)) % 5 in (0, 1) then 1 else NULL end
from sys.all_columns c1, sys.all_columns c2
および 2 つのインデックス:
create index #ix_data_n on #data (Value) include (ID) where Value is NULL
create index #ix_data_nn on #data (Value) include (ID) where Value is not NULL
データは次のようにクエリされます。
select ID from #data where Value is NULL
また
select ID from #data where Value is not NULL
クエリ プランを調べると、最初のケースではインデックス シークが実行され、2 番目のケースではインデックス スキャンが実行されていることがわかります。最初のケースでシークし、2番目にスキャンするのはなぜですか?
コメントの後に追加:
2 つのフィルタリングされたカバリングの代わりに通常のカバリング インデックスを作成すると、次のようになります。
create index #ix_data on #data (Value) include (ID)
is NULL
クエリ プランは、列内の NULL 値の % を無視して、両方の条件のインデックス シークを表示is not NULL
しています (NULL の 0%、10%、90%、または 100% は関係ありません)。フィルター処理されたインデックスが 2 つある場合、クエリ プランは常にインデックス シークを表示しis NULL
、インデックス スキャンまたはテーブル スキャン (NULL の % に応じて) になる可能性がありますが、インデックス シークではありません。したがって、本質的に違いは、条件「is not NULL」の処理方法にあります。
おそらく、インデックスが「NULL ではない」チェックのみを目的としている場合、通常のインデックスまたはフィルター処理されたインデックスのいずれかがより適切に実行され、優先されるはずですよね? どれ?
SqlServer 2008、2008r2、および 2012