Предположим, что есть таблица вида:
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
И два индекса:
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
or
select ID from #data where Value is not NULL
Если я просматриваю план запроса, я вижу, что в первом случае выполняется поиск по индексу, а во втором случае выполняется сканирование индекса. Почему он ищет в первом случае и сканирует во втором?
Дополнение после комментариев:
Если я создам обычный индекс покрытия вместо двух отфильтрованных покрытий:
create index #ix_data on #data (Value) include (ID)
План запроса показывает поиск по индексу для условий is NULL
и is not NULL
без учета % значений NULL в столбце (0% значений NULL или 10%, или 90%, или 100%, не имеет значения). Когда есть два отфильтрованных индекса, план запроса всегда показывает поиск индекса для is NULL
и может быть сканированием индекса или сканированием таблицы (в зависимости от % NULL), но это никогда не поиск индекса. Таким образом, кажется, что по существу разница заключается в том, как обрабатывается условие «не NULL».
Это означает, наверное, что если индекс предназначен только для проверки "не является NULL", то либо обычный индекс, либо фильтрованный индекс должны работать лучше и быть предпочтительнее, не так ли? Который из?
SQLServer 2008, 2008r2 и 2012
is not NULL
условию, какой тип индекса лучше, обычный или фильтрованный? - person i-one   schedule 12.07.2013