4

次のようなテーブルがあるとします。

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

4

1 に答える 1

2

表示されているクエリ プランの Seek と Scan は危険です。

どちらの場合も、適切な非クラスター化インデックスを最初から最後までスキャンし、すべての行を返すことで、クエリに応答しています。

XML クエリ プランを調べると、インデックスの Seek 述語が "#data.Value = Scalar Operator (Null)" であることがわかります。これは、すべての行がその条件を満たしているため意味がありません。

于 2013-07-14T04:04:23.167 に答える