查詢計畫是優化器的「思維導圖」。本文延續基礎圖形解讀,深入剖析**運算子內部原理、Join 三大演算法細節、統計資訊與基數估計、平行度與記憶體授予**、並給出生產級優化決策清單。
Table Scan:堆積表掃描 IAM 頁 → 資料頁,逐頁讀取,邏輯讀 = 總頁數。Clustered Index Scan:掃描叢集索引葉層 (即資料頁),順序讀取,**同樣是全掃**,只是資料有序。Index Scan:掃描非叢集索引葉層,**窄索引頁密度高**,比叢集掃描少 I/O,但仍是全掃。**優化關鍵**:將 Scan 轉為 Seek。前提:SARGable 條件 + 合適索引 + 統計資訊準確。
Index Seek:B+ 樹從根節點向下導航,僅讀取符合範圍的頁,**邏輯讀 ≈ 樹深 + 符合頁數**。Clustered Index Seek:直接定位資料列,**單次 Seek 即取得完整行**,無需 Key Lookup。非叢集索引 Seek 後,若 SELECT 清單含非索引欄位,需再按叢集鍵回查叢集索引。**大量 Key Lookup = 隨機 I/O 暴增**。解決:覆蓋索引 (INCLUDE) 或 欄位投影縮減。
Sort:需記憶體授予,不足溢寫 tempdb。索引有序可消除 Sort。Hash Match (Join/Aggregate):Build 階段建雜湊表佔記憶體,不足溢寫。**統計資訊低估基數是禍首**。Table Spool / Index Spool:臨時物化中間結果,通常為優化器應對缺索引/統計錯誤的補救,隱含效能風險。Sort,**Sort 成本往往超過 Merge 本身**。WHERE 其它條件),在合併後再篩選。| 問題 | 徵兆 | 解決 |
|---|---|---|
| 統計資訊過舊 | 實際行數 >> 預估行數,導致選錯 Join 策略、記憶體授予不足 | UPDATE STATISTICS、AUTO_UPDATE_STATISTICS ON、PERSIST_SAMPLE_PERCENT |
| 參數嗅探 | 首次編譯參數值不具代表性,計畫固化後其他參數效能極差 | OPTION (RECOMPILE)、OPTIMIZE FOR UNKNOWN、OPTIMIZE FOR (@p = typical)、Plan Guide |
| 多語句 TVF / 表變數 | 無統計資訊,預估 1 行 | 改用內嵌 TVF、臨時表 (有統計)、OPTION (RECOMPILE) |
| 相關性欠缺 | 多欄位條件獨立性假設失敗 | 多欄位統計資訊、計算欄位+索引、篩選索引 |
SET STATISTICS IO, TIME ON + 實際執行計畫 (Ctrl+M) 或 Query Store / Extended Events。sys.dm_db_index_usage_stats 讀寫比。sys.dm_db_stats_properties 修改計數器。MAXDOP、Cost Threshold for Parallelism、Resource Governor 工作負載群組。查詢計畫不是靜態圖片,而是**優化器在特定統計資訊、參數、資源限制下的動態決策**。深度理解運算子原理、Join 演算法、統計資訊機制,建立「觀察 → 假設 → 驗證 → 固化」的科學優化流程,才能在複雜生產環境中持續交付高效能查詢。