承接上篇發現 sys.dm_exec_requests 在並行查詢中無法顯示真實等待 (僅回報 CXPACKET),本文深入剖析為何 4 DOP 並行查詢會產生 21 條等待記錄,並完整定義 Scheduler、Worker、Task、Yielding 四大 SQLOS 核心物件與運作機制。
現象回顧:4 DOP 產生 21 條等待

- 去重
task_address 僅 9 個唯一 Task。
- 包含:4 個掃描 Worker、4 個消費者 Worker、1 個協調者。
- 等待類型:
LCK_M_S (鎖等待)、CXPACKET (交換港等待)、EXCHANGE (協調)。
SQLOS 任務調度四大核心定義
Scheduler (排程器) — 邏輯 CPU
- 每個邏輯 CPU (含超執行緒) 對應一個 Scheduler。
- 同一時間僅一個 Worker 擁有 Scheduler 執行權,其餘在 Runnable Queue 排隊。
- 不綁定物理 CPU,除非設定
affinity mask。
Worker (工作者) — 執行緒載體
- 1:1 對應 Windows Thread (或 Fiber 模式下的 Fiber)。
- 固定綁定一個 Scheduler,由 SQLOS 管理生命週期 (建立/回收)。
- 最大 Worker 數預設值:
| CPU 核心數 | 32-bit | 64-bit |
| ≤4 | 256 | 512 |
| 8 | 288 | 576 |
| 16 | 352 | 704 |
| 32 | 480 | 960 |
Task (任務) — 最小工作單元
- 一個 Batch (GO 分隔) = 一個 Task。
- Task 佔用 Worker 直到完成或主動等待 (鎖、I/O、同步)。
- 等待時不釋放 Worker (非搶占式),導致執行緒阻塞。
Yielding (主動讓步) — 非搶占式調度核心
Worker 定期檢查執行時間,主動歸還 Scheduler,關鍵觸發點:
- 讀取資料頁前:已執行 > 4ms。
- 每排序 64KB。
- 編譯過程中。
- 用戶端消費緩慢。
- Batch 內每句結束。
此設計避免長佔用 CPU、降低 Context Switch。
手繪關係圖

並行調度實況 (4 DOP、4 Scheduler)

- 9 Task → 9 Worker → 分佈於 4 Scheduler。
- 每 Scheduler 平均 2-3 Worker 輪流執行。
- 掃描 Worker (Producer) 產出資料 → 交換港 → 消費者 Worker (Consumer) 接收。
- 消費者在資料到達前處於
CXPACKET 等待,非閒置。


為何 sys.dm_exec_requests 失效?
- 僅回報協調者 Task 的
CXPACKET 等待。
blocking_session_id = 0 掩蓋真實阻塞者。
- 串行計劃時兩視圖一致,並行時必須用
sys.dm_os_waiting_tasks。
下篇預告
實戰驗證:雙表同時鎖定,觀察並行掃描順序;Union All 為何無法多支同時執行?持續監控腳本捕捉完整等待鏈。