經過前面四篇文章,能夠知道 Execution Plan 的四大核心:閱讀方向(粗細箭頭)、存取方式(Seek 與 Scan)、關聯策略(三大 Join),以及警告標誌(四大陷阱)。
- SQL Server 效能調校之一:不迷路的導航,Execution Plan 的閱讀方向與指標
- SQL Server 效能調校之二:看懂 Index Seek、Scan 與 Key Loop
- SQL Server 效能調校之三:三大 Join 運算子解密
- SQL Server 效能調校之四:四個常見陷阱解析
然而,當正式面對一張包含幾十個、甚至上百個節點的巨大執行計畫時,很容易再度感到不知所措;這時候,需要的是一套系統化的除錯 SOP。效能調校的心法「一次只動一個地方,並且永遠以數據驗證差異。」以下是從一團亂麻中找出解方的步驟:
步驟一:鎖定「最貴」的目標 (Find the Most Expensive)
面對龐大的執行計畫,不要試圖由右至左把每個節點都看懂,需要「擒賊先擒王」。
- 尋找 Cost % 最高的節點:
每個節點下方都會標示該步驟佔整句查詢成本的百分比;直接掃視全圖,把目光鎖定在那些標示 40%、60% 甚至 90% 的高成本節點上。 - 追蹤「最粗的箭頭」:
尋找哪兩個節點之間傳遞了異常龐大的資料量,特別是「漏斗效應」:如果一個節點右邊進來很粗的箭頭,左邊出去卻變得很細,這代表它浪費了大量資源在過濾不必要的資料。
限縮範圍,挑出 1 到 2 個效能最差的局部節點作為第一階段的開刀對象,不要急著對整句 SQL 做全域(Global)的改寫。
步驟二:辨識症狀與警告 (Identify Symptoms)
鎖定可疑節點後,把滑鼠懸停(Hover)在該節點上,開始進行「健康檢查」:
有沒有黃色驚嘆號?
如果是 CONVERT_IMPLICIT,就去檢查程式端參數型別是不是和資料庫不符(尤其是字串型別)。如果是 Spill to TempDB,先去檢查統計資料是否過期。
它是怎麼存取資料的?
如果是 Table Scan 或 Clustered Index Scan,檢查 WHERE 條件欄位是不是漏建了索引,或者條件寫法讓索引失效了(例如在欄位上套用函數)。如果是 Index Seek,點開屬性檢查有沒有發生了「殘餘篩選條件(Residual Predicate)」,導致讀取了一堆資料卻被拋棄。
有沒有跟著 Key Lookup?
如果高成本節點是 Key Lookup,去看看 SELECT 了哪些多餘的欄位,或者把它們加入現有索引的 INCLUDE 清單中。
步驟三:戳破 Optimizer 的幻覺 (Check Row Estimates)
很多時候,SQL Server 選了極差的執行計畫(例如:不該用 Hash Match 卻用了),是因為它「猜錯了資料量」。
- 比對預估與實際: 在節點的詳細屬性中,仔細比對 Estimated Number of Rows(預估資料列數) 與 Actual Number of Rows(實際資料列數)。
落差代表什麼?
如果 Optimizer 預估只有 10 筆,實際卻跑出 100 萬筆,它就會錯配過少的記憶體(導致 Spill)或選錯 Join 方式(導致 Nested Loops 癱瘓)。
如何修正幻覺?
這種落差通常是因為「統計資料(Statistics)」太久沒更新,不要急著改語法,先執行 UPDATE STATISTICS 資料表名稱,有極高的機率,更新完後 Optimizer 就會自動切換成完美的執行計畫。
步驟四:對症下藥與驗證 (Prescribe and Verify)
找出了病因,最後一步就是採取行動,請依循以下流程:
- 開啟驗證數據:
在執行任何修改前,請先在 SSMS 執行SET STATISTICS IO ON與SET STATISTICS TIME ON,記錄下原本的 Logical reads(邏輯讀取次數)與耗時。 - 單一變數法則:
一次只做一個改變,要嘛新建一個索引,要嘛改寫一段WHERE,要嘛更新統計資料;不要同時做兩件事,否則會不知道是哪個動作起了作用。 - 比對前後差異:
再次執行查詢,查看新的 Execution Plan;原本的 Scan 變成 Seek 了嗎?黃色警告消失了嗎?更重要的是,Logical reads 是否有顯著下降?(在資料庫的世界裡,降低 Logical reads 才是真正降低伺服器負載的硬指標)。
透過這系列文章,從觀念建立一路走到實戰除錯,明白了 SQL Server 的 Execution Plan 不是死板的系統報告,而是 Query Optimizer 在訴說「我從這裡拿資料,我用這種方式比對,我在這裡遇到了記憶體不足的困難……」
效能調校,是一場開發者與資料庫的對話,下次遇到跑出 Timeout 的 SQL 查詢時,大膽地點開 Execution Plan,看懂它的求救信號,人人都能成為精準治癒效能痼疾的資料庫神醫!














