2011/04/27

Effective Optional Parameters in MS SQL Use Like: 續上篇追縱報告

<< 前期提要 在這 >>
在前天發現使用「like '%'+@LastName+'%'」會讓執行計劃(Execution Plan)跑出索引搜尋(Seek)後,因為我還是無法確定這是否是有效的,鼓起勇氣在隔天中午寫了封信詢問公司的前輩Sky大大,終於在當天下午5點多,應該是很繁忙的Sky大回了信給我,肯定了我的測試,並且也幫我修正了一個小地方,而修正後的查詢指令(SQL Script)才真正的用到 Seek,信中指令如下:
use AdventureWorks
go
--繼續用前一篇的索引
create index icl_LastName_Title on Person.Contact(LastName, Title)
 include(ContactID, FirstName)
go
--等等要用的變數
declare @LastName nvarchar(50)='Adams'

--原指令,和前一篇不同,當@LastName有輸入值時才搜尋"相同名稱"
select ContactID, Title, LastName, FirstName
from Person.Contact
where (@LastName='' OR LastName=@LastName)
 and Title='Mr.'

執行計劃為,(索引掃描(scan))


STATISTICS IO 為,
資料表 'Contact'。掃描計數 1,邏輯讀取 134,實體讀取 0,讀取前讀取 0,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。

SQL Server Profiler 為,


--增加 like '%'+@LastName+'%' 的指令
select ContactID, Title, LastName, FirstName
from Person.Contact
where LastName like '%'+@LastName+'%' -- <--這邊
 and (@LastName='' OR LastName=@LastName)
 and Title='Mr.'

執行計劃為,(變成索引搜尋(seek)了)


STATISTICS IO 為,(重點!邏輯讀取數沒變,還是134)
資料表 'Contact'。掃描計數 1,邏輯讀取 134,實體讀取 0,讀取前讀取 0,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。

SQL Server Profiler 為,

而上述 Profiler 側錄的結果,Duration 也沒有比較快,而且邏輯讀取數沒變,
所以在此可以斷定,我的修改沒有用XD!
不過薑是老的辣,Sky大拿掉一個地方後,一切豬羊變色! 請先看修改後的指令碼,
--Sky大修改後的指令
select ContactID, Title, LastName, FirstName
from Person.Contact
where LastName like @LastName+'%' 
 and (@LastName='' OR LastName=@LastName)
 and Title='Mr.'

執行計劃為,


STATISTICS IO 為,(重點!邏輯讀取從134減少為3)
資料表 'Contact'。掃描計數 1,邏輯讀取 3,實體讀取 0,讀取前讀取 0,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。

SQL Server Profiler 為,


眼尖的人應該發現到了,
其實就是上一篇2.裡寫到的「like時不要用前面的'%'」,
(真是汗顏,自己寫的自己都忘了)
拿掉前面的 '%'+ 後,一切就像水到渠成,功能還是能用,索引終於發揮功效,Happy Ending!!

感謝Sky大的提點!謝謝!

沒有留言:

張貼留言