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


 

sqlserver 的篩選索引(filter index)與常規的非篩選索引,加了一定的filter條件,可以按照某些條件對表中的字段進行索引,但是filter 索引在查詢 使用上,並不等同於常規的索引,
如果忽略了這些差異,可能會造成潛在的問題,因此在使用filter索引的時候,一定要結合具體的查詢,做充分的測試。

測試case

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索引

如果是正常的索引,也即不加filter條件,如下創建測試表上的索引

--col2和col3上,如果是常規索引(非篩選索引)
create index idx_col2 on test_filter_index(col2,col3) 
GO

如下,只要是按照索引的前導列進行查詢或join,都可以使用到索引

 

filter索引

如果在創建索引的時候增加filter條件

--刪除之前創建的索引
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索引

其實不難理解,為什么上面兩種情況無法使用到創建的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索引

查詢是否可以使用到filter索引,只有滿足當前的查詢結果集,一定是屬於索引的filter篩選之后的子集的情況下,才能使用到filter索引,否則都無法使用到filter索引
filter索引只能針對具體的語句進行創建,而不能作為通用的索引使用,這個比較簡單,記錄一下,防止犯錯。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM