假设有一个像这样的表:
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
或者
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