[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)
CPU和I/O 統計資料(logical reads:581)。
執行計畫(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)
CPU和I/O 統計資料(logical reads:145)。
執行計畫(cost:0.104)。
或許有人還是不想改寫那麼多,可能會問是否還有其他方法來處理,
當然是有的,你也可以利用提示(forceseek)來處理,
但查詢效能的改善不會太多,
而且你的資料庫版本要SQL2008以後才支援該資料表提示。
結論:
可以看到使用反向查詢的成本相當昂貴且耗時,而且也無法真正利用索引改善效能,
這不但讓你所建立的索引無三小路用,也浪費硬碟空間和記憶體(Buffer Pool)資源,
如果可以的話,請盡力將系統中所有非SARG SQL改寫成符合SARG SQL,
因為任何資料庫效能優化都不及調校一句高成本 SQL 所帶來的效益。