--Setup, actual queries after the space
--create table fltrind (a integer,b integer)
truncate table fltrind
DROP INDEX fltrind.nf
DROP INDEX fltrind.f
DECLARE @i integer
SET @i=0
while @i<100
BEGIN
INSERT INTO fltrind(a) values(@i)
SET @i=@i+1
END
INSERT INTO fltrind(a,b) values(9000,0900)
insert into fltrind(a,b)
select top 100000 f1.a,f1.b from fltrind f1 , fltrind f2
create nonclustered index nf on fltrind(b) INCLUDE(a)
create nonclustered index f on fltrind(b) INCLUDE(a) where b is not null
UPDATE STATISTICS fltrind WITH FULLSCAN
select a from fltrind where b is not null
DROP INDEX fltrind.nf
UPDATE STATISTICS fltrind WITH FULLSCAN
select a from fltrind where b is not null
查看查询计划,只要存在非过滤索引,就不会使用过滤索引。知道为什么,以及如何让它使用过滤索引?
删除非过滤索引nf
会使优化器使用过滤索引f
。
事实上,增加行数以使超过 10% 的行符合条件会导致在删除非过滤索引时进行表扫描。
因为 SQL Server 可以跳过 NULL 行来启动范围扫描,所以这两个索引的成本是相同的,所以这基本上是优化器的一次抛硬币。在SQL Sentry Plan Explorer * 中查看默认情况下的计划以及提示索引时的计划(点击放大):
因为这是一个折腾,我不知道你会从强制SQL Server 选择两个同样有效的选项之一中得到什么好处。
*
免责声明:我为 SQL Sentry 工作。