SQL Server 效能調校之五:從發現問題到解決問題的黃金步驟

更新 發佈閱讀 6 分鐘

經過前面四篇文章,能夠知道 Execution Plan 的四大核心:閱讀方向(粗細箭頭)、存取方式(Seek 與 Scan)、關聯策略(三大 Join),以及警告標誌(四大陷阱)。

  1. SQL Server 效能調校之一:不迷路的導航,Execution Plan 的閱讀方向與指標
  2. SQL Server 效能調校之二:看懂 Index Seek、Scan 與 Key Loop
  3. SQL Server 效能調校之三:三大 Join 運算子解密
  4. 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 ONSET STATISTICS TIME ON,記錄下原本的 Logical reads(邏輯讀取次數)與耗時。
  • 單一變數法則:
    一次只做一個改變,要嘛新建一個索引,要嘛改寫一段 WHERE,要嘛更新統計資料;不要同時做兩件事,否則會不知道是哪個動作起了作用。
  • 比對前後差異:
    再次執行查詢,查看新的 Execution Plan;原本的 Scan 變成 Seek 了嗎?黃色警告消失了嗎?更重要的是,Logical reads 是否有顯著下降?(在資料庫的世界裡,降低 Logical reads 才是真正降低伺服器負載的硬指標)。

透過這系列文章,從觀念建立一路走到實戰除錯,明白了 SQL Server 的 Execution Plan 不是死板的系統報告,而是 Query Optimizer 在訴說「我從這裡拿資料,我用這種方式比對,我在這裡遇到了記憶體不足的困難……」

效能調校,是一場開發者與資料庫的對話,下次遇到跑出 Timeout 的 SQL 查詢時,大膽地點開 Execution Plan,看懂它的求救信號,人人都能成為精準治癒效能痼疾的資料庫神醫!



留言
avatar-img
愷的大冒險 Kai's Adventure
6會員
18內容數
這裡記錄軟體工程相關工具、技能與學習的探索歷程,偶爾分享角落生物的美好日常,希望能透過文字與更多人交流,如果你對這些主題感興趣歡迎留言,讓我們一起碰撞出更多火花!
2026/05/10
在調校 SQL Server 查詢效能時,有些問題容易被忽略,卻也容易造成嚴重的效能退化:Missing Index、Implicit Conversion、Spill to TempDB、以及 Residual Predicate。整理這四種問題的成因、症狀與修正方式,並說明彼此之間容易混淆的關鍵
Thumbnail
2026/05/10
在調校 SQL Server 查詢效能時,有些問題容易被忽略,卻也容易造成嚴重的效能退化:Missing Index、Implicit Conversion、Spill to TempDB、以及 Residual Predicate。整理這四種問題的成因、症狀與修正方式,並說明彼此之間容易混淆的關鍵
Thumbnail
2026/05/09
延續上篇,當我們確保了資料存取的效率(消滅了不必要的 Scan 與 Key Lookup)後,接下來要面對的就是關聯式資料庫最核心的動作:將多張資料表結合在一起(Join)。
Thumbnail
2026/05/09
延續上篇,當我們確保了資料存取的效率(消滅了不必要的 Scan 與 Key Lookup)後,接下來要面對的就是關聯式資料庫最核心的動作:將多張資料表結合在一起(Join)。
Thumbnail
2026/05/08
在上一篇中,我們建立了閱讀執行計畫的「方向感」,學會透過箭頭粗細找出塞車路段。順著箭頭一路往右追溯到最源頭,我們就會看到 SQL Server 是如何進入資料庫「拿資料」的。 這一步至關重要。因為資料庫系統最大的效能瓶頸往往在於磁碟 I/O(資料讀寫)。你是在「精準尋找」還是在「盲目翻找」,決定了
Thumbnail
2026/05/08
在上一篇中,我們建立了閱讀執行計畫的「方向感」,學會透過箭頭粗細找出塞車路段。順著箭頭一路往右追溯到最源頭,我們就會看到 SQL Server 是如何進入資料庫「拿資料」的。 這一步至關重要。因為資料庫系統最大的效能瓶頸往往在於磁碟 I/O(資料讀寫)。你是在「精準尋找」還是在「盲目翻找」,決定了
Thumbnail
看更多
你可能也想看
Thumbnail
5 月,方格創作島正式開島。這是一趟 28 天的創作旅程。活動期間,每週都會有新的任務地圖與陪跑計畫,從最簡單的帳號使用、沙龍建立,到帶著你從一句話、一張照片開始,一步一步找到屬於自己的創作節奏。不需要長篇大論,不需要完美的文筆,只需要帶上你今天的日常,就可以出發。征服創作島,抱回靈感與大獎!
Thumbnail
5 月,方格創作島正式開島。這是一趟 28 天的創作旅程。活動期間,每週都會有新的任務地圖與陪跑計畫,從最簡單的帳號使用、沙龍建立,到帶著你從一句話、一張照片開始,一步一步找到屬於自己的創作節奏。不需要長篇大論,不需要完美的文筆,只需要帶上你今天的日常,就可以出發。征服創作島,抱回靈感與大獎!
Thumbnail
當時間變少之後,看戲反而變得更加重要——這是在成為母親之後,我第一次誠實地面對這一件事:我沒有那麼多的晚上,可以任性地留給自己了。看戲不再只是「今天有沒有空」,而是牽動整個週末的結構,誰應該照顧孩子,我該在什麼時間回到家,隔天還有沒有精神帶小孩⋯⋯於是,我不得不學會一件以前並不擅長的事:挑選。
Thumbnail
當時間變少之後,看戲反而變得更加重要——這是在成為母親之後,我第一次誠實地面對這一件事:我沒有那麼多的晚上,可以任性地留給自己了。看戲不再只是「今天有沒有空」,而是牽動整個週末的結構,誰應該照顧孩子,我該在什麼時間回到家,隔天還有沒有精神帶小孩⋯⋯於是,我不得不學會一件以前並不擅長的事:挑選。
Thumbnail
※ 什麼是ORDER BY? 可以讓SELECT出來的結果,根據你想要的方式排序。簡單說,用於對查詢結果進行排序。 ※ 語法: SELECT select_list FROM table_name ORDER BY column1 [ASC|DESC], column2 [ASC|DESC]
Thumbnail
※ 什麼是ORDER BY? 可以讓SELECT出來的結果,根據你想要的方式排序。簡單說,用於對查詢結果進行排序。 ※ 語法: SELECT select_list FROM table_name ORDER BY column1 [ASC|DESC], column2 [ASC|DESC]
Thumbnail
見諸參與鄧伯宸口述,鄧湘庭於〈那個大霧的時代〉記述父親回憶,鄧伯宸因故遭受牽連,而案件核心的三人,在鄧伯宸記憶裡:「成立了成大共產黨,他們製作了五星徽章,印刷共產黨宣言——刻鋼板的——他們收集中共空飄的傳單,以及中國共產黨中央委員會有關文化大革命決議文的英文打字稿,另外還有手槍子彈十發。」
Thumbnail
見諸參與鄧伯宸口述,鄧湘庭於〈那個大霧的時代〉記述父親回憶,鄧伯宸因故遭受牽連,而案件核心的三人,在鄧伯宸記憶裡:「成立了成大共產黨,他們製作了五星徽章,印刷共產黨宣言——刻鋼板的——他們收集中共空飄的傳單,以及中國共產黨中央委員會有關文化大革命決議文的英文打字稿,另外還有手槍子彈十發。」
Thumbnail
本篇文章是作者自學 SQL 的筆記,詳述資料庫中的四種主要語言類別:DDL、DML、TCL 及 DCL,每類別對應的功能與常見操作一一列舉,並深入探討交易的特性及其 ACID 原則。此外,文章還解釋了資料庫的正規化及反正規化的必要性,對於學習 SQL 的讀者有很大的幫助。
Thumbnail
本篇文章是作者自學 SQL 的筆記,詳述資料庫中的四種主要語言類別:DDL、DML、TCL 及 DCL,每類別對應的功能與常見操作一一列舉,並深入探討交易的特性及其 ACID 原則。此外,文章還解釋了資料庫的正規化及反正規化的必要性,對於學習 SQL 的讀者有很大的幫助。
Thumbnail
※ 語法 SELECT select_list FROM table_name​ ※ 解析順序 From:從哪裡拿? SELECT:要 "拿什麼" 資料? ※ 使用場景: Single column(單一欄位): Multiple column(多個欄位): All colu
Thumbnail
※ 語法 SELECT select_list FROM table_name​ ※ 解析順序 From:從哪裡拿? SELECT:要 "拿什麼" 資料? ※ 使用場景: Single column(單一欄位): Multiple column(多個欄位): All colu
Thumbnail
在進行SQL查詢邏輯更改時,需要適當地使用SubQuery和join來達到新的排序需求。本文將介紹原本的撈取邏輯、需求以及如何使用SubQuery來解決新的排序需求。
Thumbnail
在進行SQL查詢邏輯更改時,需要適當地使用SubQuery和join來達到新的排序需求。本文將介紹原本的撈取邏輯、需求以及如何使用SubQuery來解決新的排序需求。
Thumbnail
當代名導基里爾.賽勒布倫尼科夫身兼電影、劇場與歌劇導演,其作品流動著強烈的反叛與詩意。在俄烏戰爭爆發後,他持續以創作回應專制體制的壓迫。《傳奇:帕拉贊諾夫的十段殘篇》致敬蘇聯電影大師帕拉贊諾夫。本文作者透過媒介本質的分析,解構賽勒布倫尼科夫如何利用影劇雙棲的特質,在荒謬世道中尋找藝術的「生存之道」。
Thumbnail
當代名導基里爾.賽勒布倫尼科夫身兼電影、劇場與歌劇導演,其作品流動著強烈的反叛與詩意。在俄烏戰爭爆發後,他持續以創作回應專制體制的壓迫。《傳奇:帕拉贊諾夫的十段殘篇》致敬蘇聯電影大師帕拉贊諾夫。本文作者透過媒介本質的分析,解構賽勒布倫尼科夫如何利用影劇雙棲的特質,在荒謬世道中尋找藝術的「生存之道」。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News