星期一, 8月 20, 2018

[SQL] 避免欄位比較

閱讀 Microsoft SQL Server Performance Tuning 效能調校的 SARG 介紹時,提到 [資料欄位 運算子 資料欄位] 是不符合 SARG 原則,以往看到的資料大多是強調 [資料欄位 符合 SARG 運算子 <常數或變數>] 符合 SARG,最近調校有剛好發現很多 [資料欄位 運算子 資料欄位] 語法,不太能從 TSQL 語法變化來提升效能,所以重新閱讀書籍內容時特別有感

SARG 簡易筆記
SARG 意義:在查詢子句中,SARG 代表用來搜尋的常數或變數可以直接與索引鍵值做比較 
SARG 運算子列表
  • 符合:=、<、>、>=、<=、BETWEEN、LIKE (看 % 位置) 
  • 不符合:NOT、!=、<>、!>、!<、NOT EXISTS、NOT IN、NOT LIKE 
SARG 格式理論
  • 符合:
    • 資料欄位 符合 SARG 運算子 <常數或變數>
    • <常數或變數> 符合 SARG 運算子 資料欄位
  • 不符合:資料欄位 運算子 資料欄位
物流申請例子來說明,商業邏輯很簡單,Transport 是物流申請資料,Car 是派車資料檔頭、CarDetail 則是 Transport 資訊和數量,Transport 資料是可以存在多張派車單內,所以要知道待運送的 Transport 資料,必須用下述語法去比對出來
SELECT
  T.*
  , D.TranNO
  , ISNULL(D.TranQty, 0) AS TranQty
FROM Transport AS T
  LEFT JOIN 
    (
      SELECT
        TranNO
        , SUM(TranQty) AS TranQty
      FROM CarDetail
      GROUP BY TranNO
    ) AS D ON T.TranNO = D.TranNO
WHERE (D.TranNO IS NULL
  OR T.Qty > D.TranQty)    

當時這樣設計看執行 Statistics 覺得很 OK、還覺得執行計劃有跑出平行處理很不錯,時過境遷後,現在看到平行處理就覺得事情不尋常,Orz

醜醜的執行計畫,通通從 Transport 和 CarDetail 跑 Clustered Index Scan 來處理

[SQL] 避免 資料欄位 運算子 資料欄位-1

有該篇 - [SQL] 利用 UNION ALL 取代 OR 條件 經驗,當然是要來嘗試一下
SELECT
  T.* ,
  0 AS TransQty
FROM Transport AS T
WHERE NOT EXISTS
  (
    SELECT 1 FROM CarDetail AS D WHERE T.TranNO = D.TranNO
  )
UNION ALL
SELECT
  T.*
  , D.TranQty
FROM Transport AS T
  JOIN
    (
      SELECT
        TranNO
        , SUM(TranQty) AS TranQty
      FROM CarDetail
      GROUP BY TranNO
    ) AS D ON T.TranNO = D.TranNO
WHERE T.Qty > D.TranQty
改完之後發現更慘,Statistics 為原本兩倍左右,執行計畫也肥了不少

[SQL] 避免 資料欄位 運算子 資料欄位-2

無法從語法獲得改善,就只能動 Table Schema 來改善囉

沒有留言:

張貼留言