[SQL SERVER][Performance] 避免反向查詢

[SQL SERVER][Performance] 避免反向查詢

當我知道某句SQL耗用大量成本且查詢相當緩慢時,

表示我可能無法躲掉 SQL Tuning 苦工,

而第一步往往就是SARG格式改寫,

SQL符合SARG格式可讓查詢語句利用索引快速搜尋資料(

前提是你已有正確建立索引),

盡力改寫SQL符合SARG格式永遠是 SQL Tuning 中不可缺少又重要的環節(大部分sql tuning tools所達不到),

這篇我來測試一下為什麼要避免反向查詢,因為反向查詢佔絕大多數案例,

但對於開發人員來說多寫幾個字真的不會多花你幾秒鐘時間,

而且還可以大幅改善你的SQL查詢效能,何樂而不為呢....

 

查詢需求: ReferenceOrderLineID 排除  0,1,2,3,5,9,15,19,24,28,32,40,44

 

大多數開發人員幾乎會使用 not in (因為直覺也方便)

select TransactionDate,TransactionType,Quantity,ActualCost 
from production.TransactionHistory 
where ReferenceOrderLineID not in (0,1,2,3,5,9,15,19,24,28,32,40,44)

 

 

image

CPU和I/O 統計資料(logical reads:581)。

 

image

image

執行計畫(cost:0.554)。

 

可以看到執行計畫使用索引掃描作業,索引掃描作業資料列數目20931,

查詢已有大海撈針的需求,但卻使用索引掃描,這顯然不太正常,

下面是改寫後的結果,你將看到反向操作的成本是相當昂貴且耗時的。

 

改寫SQL

select TransactionDate,TransactionType,Quantity,ActualCost 
from production.TransactionHistory 
where (ReferenceOrderLineID >=4 and ReferenceOrderLineID <5)
or (ReferenceOrderLineID >=6 and ReferenceOrderLineID<9)
or (ReferenceOrderLineID >=10 and ReferenceOrderLineID<15)
or (ReferenceOrderLineID >=16 and ReferenceOrderLineID<19)
or (ReferenceOrderLineID >=20 and ReferenceOrderLineID<24)
or (ReferenceOrderLineID >=25 and ReferenceOrderLineID<28)
or (ReferenceOrderLineID >=29 and ReferenceOrderLineID<32)
or (ReferenceOrderLineID >=33 and ReferenceOrderLineID<40)
or (ReferenceOrderLineID >=41 and ReferenceOrderLineID<44)
or (ReferenceOrderLineID >=45)  

 

 

image

CPU和I/O 統計資料(logical reads:145)。

 

image

image

執行計畫(cost:0.104)。

 

或許有人還是不想改寫那麼多,可能會問是否還有其他方法來處理,

當然是有的,你也可以利用提示(forceseek)來處理,

但查詢效能的改善不會太多,

而且你的資料庫版本要SQL2008以後才支援該資料表提示。

 

結論:

可以看到使用反向查詢的成本相當昂貴且耗時,而且也無法真正利用索引改善效能,

這不但讓你所建立的索引無三小路用,也浪費硬碟空間和記憶體(Buffer Pool)資源,

如果可以的話,請盡力將系統中所有非SARG SQL改寫成符合SARG SQL,

因為任何資料庫效能優化都不及調校一句高成本 SQL 所帶來的效益。