sqlserver 的筛选索引(filter index)与常规的非筛选索引,加了必定的filter条件,能够按照某些条件对表中的字段进行索引,可是filter 索引在查询 使用上,并不等同于常规的索引,
若是忽略了这些差别,可能会形成潜在的问题,所以在使用filter索引的时候,必定要结合具体的查询,作充分的测试。sql
测试caseide
if object_id('test_filter_index') is not null drop table test_filter_index GO create table test_filter_index ( id int identity(1,1) not null primary key, col2 varchar(10), col3 varchar(10), create_date datetime ) GO --写入10W行测试数据,col2 col3非空 insert into test_filter_index select concat('A',cast(rand()*1000000 as int)),concat('B',cast(rand()*1000000 as int)),getdate() GO 100000 --写入1W行测试数据,col2 col3为空 insert into test_filter_index select null,null,getdate() GO 10000
非filter索引sqlserver
若是是正常的索引,也即不加filter条件,以下建立测试表上的索引测试
--col2和col3上,若是是常规索引(非筛选索引) create index idx_col2 on test_filter_index(col2,col3) GO
以下,只要是按照索引的前导列进行查询或join,均可以使用到索引spa
filter索引3d
若是在建立索引的时候增长filter条件code
--删除以前建立的索引 drop index idx_col2 on test_filter_index --col2和col3上,若是是筛选索引(增长col2和col3上的筛选条件) create index idx_col2 on test_filter_index(col2,col3) where col2 is not null and col3 is not null GO
在执行上述的两个查询,会发现,尽管使用的查询条件为索引的前导列,可是扔没法使用到上面建立的filter索引server
其实不难理解,为何上面两种状况没法使用到建立的filter索引?因为在建立索引的时候,增长筛选条件,这个索引树种的数据,多是不彻底符合查询语义的
就好比select * from test_filter_index where col2 = 'A632395',除了 col2 = 'A632395'这个条件以外,对于col3字段,潜在两种符合条件的数据
第一种:select * from test_filter_index where col2 = 'A632395' and col3 is null
第二种:select * from test_filter_index where col2 = 'A632395' and col3 is not null
若是走了filter索引,也即idx_col2 ,查询出来的结果可能就是不完整的,所以不会使用到idx_col2 这个索引
事实上,执行计划很清楚地显示了,什么状况下才能够用到filter索引,只有查询条件的数据被filter索引的筛选条件覆盖,或者说查询条件是filter条件的子集,才有可能用到filter索引blog
查询是否可使用到filter索引,只有知足当前的查询结果集,必定是属于索引的filter筛选以后的子集的状况下,才能使用到filter索引,不然都没法使用到filter索引
filter索引只能针对具体的语句进行建立,而不能做为通用的索引使用,这个比较简单,记录一下,防止犯错。索引