sqlserver 篩選索引(filter index)在使用時須要注意的事項

 

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索引只能針對具體的語句進行建立,而不能做爲通用的索引使用,這個比較簡單,記錄一下,防止犯錯。索引

相關文章
相關標籤/搜索