[SQL SERVER]謹慎使用索引檢視

OLTP環境中,使用索引檢視的base資料表最好皆是唯讀。

很久以前我介紹過索引檢視,索引檢視大部分可以帶來極大的效能改善,

BOL建議不要使用異動頻率高資料表來建立索引檢視,

但因為索引檢視提升查詢效能實在讓我難以抵擋誘惑,

所以新系統我抱者試試看心態上線,結果就是花了快3天時間,改寫2百多隻SP、1百多隻function,

最後完完整整刪除索引檢視,才解決blocking query、deadlock、query timeout問題,

拿異動頻率高相關資料表建立索引檢視,結果就是增加blocking並提高deadlock發生機會,

下面我簡單還原我當時系統上線情況

 

1.更多的blocking

--session 1
begin tran
insert into indexviewtest
select 1,1,1

--  rollback

--session 2
begin tran
insert into indexviewtest
  select 2,1,1
rollback 

這兩條session在沒有索引檢視下並不會發生blocking。

建立索引檢視

--create indexed view
create view idvtest WITH SCHEMABINDING 
as 
select  c1, 
  COUNT_BIG(*) AS total 
from dbo.indexviewtest 
group by c1

create unique clustered index cidx_idvtest
on idvtest(c1)

 

檢視索引檢視後再次執行上面script後,就可以輕易看到session2被session1 blocking

--create indexed view
create view idvtest WITH SCHEMABINDING 
as 
select  c1, 
  COUNT_BIG(*) AS total 
from dbo.indexviewtest 
group by c1

create unique clustered index cidx_idvtest
on idvtest(c1)

image

 

2連結資料行資料差異太大,使用索引檢視效能反而更差

BOL提到可以把常用相關資料表連結改寫成索引檢視,但這部分還需考慮資料差異不可過大,

以免查詢效能沒有提升反而變得更差,我簡單測試還原該情況

兩者資料表為1:10001,及一筆父資料有約一萬筆子資料

把這2個資料表連結改用索引檢視

create view Pindexviewtestall WITH SCHEMABINDING 
as 
select  t1.c1, t1.c2,  t2.c1 as [cc1],  t2.c3    
from dbo.Pindexviewtest t1 join dbo.indexviewtest t2 on t1.c1=t2.c2


create unique clustered index cidx_Pindexviewtestall
on Pindexviewtestall(c1,cc1)

執行下面TSQL查詢索引檢視

select c1, c2,  cc1,  c3 
  from dbo.Pindexviewtestall 

可以看到SQL Server不選用索引檢視,反而採取兩個資料表的full scan,整體執行計畫成本(0.1333)。

相關I/O

 

使用NOEXPAND 提示強制走索引檢視

select c1, c2,  cc1,  c3 
  from dbo.Pindexviewtestall with(NOEXPAND)

整體執行計畫成本變高(1.866)。

I/O一整個暴增。

 

參考

[SQL SERVER][Performance]善用Indexed View#1簡介

[SQL SERVER][Performance]善用Indexed View#2測試