並行查詢 (Parallel Query) 利用多 CPU 核心將大查詢拆分為多執行緒同時執行,顯著縮短大表掃描、連接、聚合、排序等重負載操作耗時。本文解析三階段決策流程、關鍵配置 (MAXDOP、Cost Threshold)、四大注意事項與實戰調優策略。
一、並行查詢三階段決策流程
- 優化器評估:查詢優化器分析 SQL,判斷並行計畫成本是否低於串行。不並行條件:
- 串行計畫估算成本更低。
- 查詢成本 <
Cost Threshold for Parallelism (預設 5,極低,建議調高)。
- 包含無法並行運算子 (標量 UDF、某些 CLR、動態游標、
TOP 配合 ORDER BY 等)。
- 決定平行度 (DOP - Degree of Parallelism):
- 實例級:
sp_configure 'max degree of parallelism' (預設 0 = 所有邏輯 CPU)。
- 查詢級:
OPTION (MAXDOP N) 覆蓋實例設定。
- Resource Governor:工作負載群組
MAX_DOP 限制。
- 實際 DOP ≤ 設定上限,優化器依計畫複雜度、統計資訊動態決定。
- 執行階段:執行引擎初始化交換運算子 (Exchange: Distribute Streams / Repartition Streams / Gather Streams),分配執行緒,執行並行計畫。執行期間 DOP 不變;下次編譯重新評估。
二、關鍵配置參數
| 參數 | 預設 | 建議值 | 說明 |
max degree of parallelism (MAXDOP) | 0 (所有 CPU) | ≤ 8 (OLTP)、≤ 核心數/2 (DW) | 防止單查詢佔盡 CPU、降低協調開銷 |
cost threshold for parallelism | 5 | 50-100 (OLTP)、20-50 (混合) | 過低導致小查詢並行,協調成本超過收益 |
max worker threads | 0 (自動) | 通常保持自動 | 執行緒池上限,不足時降級串行 |
affinity mask | 0 | 專用場景綁核 | CPU 親和性,較少調整 |
-- 修改實例級 MAXDOP 為 8
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'max degree of parallelism', 8; RECONFIGURE;
-- 修改並行門檻為 50
EXEC sp_configure 'cost threshold for parallelism', 50; RECONFIGURE;
三、四大注意事項 (避坑指南)
- 硬體限制:單 CPU 機器無並行;執行緒池不足時自動降級串行 (錯誤日誌記錄
Parallel query downgraded)。
- 不適用所有查詢:僅大表連接、大量聚合、大結果集排序、建立索引、
DBCC CHECKDB、大量匯入/匯出受益。簡單點查、小範圍掃描並行反而慢。
- 資料量門檻:優化器依統計資訊估算行數,行數過少不並行。測試需製造足夠資料量。
- 同一查詢不同時段 DOP 可能不同:系統負載、可用執行緒、統計資訊更新均影響實際 DOP。壓測需固定環境、多次取中位數。
四、實戰調優策略
1. 實例級保守,查詢級精準開啟
-- 實例級設定較低 (如 4 或 8)
-- 關鍵報表/ETL 查詢顯式指定高 DOP
SELECT * FROM fact_sales
WHERE sale_date >= '2024-01-01'
OPTION (MAXDOP 16, USE HINT('ENABLE_PARALLEL_PLAN_PREFERENCE'));
2. 識別並行收益查詢
-- 找出高 CPU、高 Duration、並行計畫的查詢
SELECT TOP 20
qs.total_worker_time / qs.execution_count AS Avg_CPU_ms,
qs.total_elapsed_time / qs.execution_count AS Avg_Duration_ms,
qp.query_plan.value('(//@DegreeOfParallelism)[1]', 'int') AS DOP,
SUBSTRING(qt.text, qs.statement_start_offset/2+1,
(CASE WHEN qs.statement_end_offset = -1 THEN LEN(qt.text)
ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) AS QueryText
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
WHERE qp.query_plan.exist('//@DegreeOfParallelism') = 1
ORDER BY Avg_CPU_ms DESC;
3. 解決並行不均勻 (Skew)
- 資料傾斜導致某執行緒處理過多行 → 更新統計、建立過濾索引、改寫查詢 (如
CASE WHEN 分桶)。
- 交換運算子
Repartition Streams 使用 Hash 分佈,鍵值分佈不均 → 改用 Range Partitioning (分區表) 或手動分桶。
4. CXPACKET / CXCONSUMER 等待分析
CXPACKET:生產者等待消費者 (正常協調等待),高比例表示負載不均或過度並行。
CXCONSUMER (SQL 2016 SP2+):消費者等待生產者,通常無害。
- 調優:降低 MAXDOP、提高 Cost Threshold、改善索引減少掃描範圍。
五、版本演進提示
| 版本 | 關鍵變更 |
| 2005 | 引入並行查詢、MAXDOP、Cost Threshold |
| 2012 | Columnstore 索引並行掃描、Batch Mode |
| 2016 | CXCONSUMER 等待類型、USE HINT、自動軟 NUMA |
| 2019 | 批次模式自適應連接、記憶體授予回饋、MAXDOP 資料庫範圍設定 |
| 2022 | 並行查詢記憶體授予回饋增強、OPTIMIZE_FOR_SEQUENTIAL_KEY |