我和一个非常老的 DBA 一起工作,他说了很多奇怪的话。Dude 有一本 O'Reilly 的书,封面上只有一个变形虫。
午餐时我们讨论了并行性,因为我们的新服务器有 24 个内核。他说,在并行计划中,每个操作员都会获得 DOP 线程。因此,如果您有 MAXDOP 8 并且您的查询有 4 个并行运算符,它将一次使用 32 个线程。
这似乎不对,因为您会很快用完线程。
我还读到整个查询可能只有 8 个,这似乎太少了。
为什么我在 sysprocesses 中看到每个 SPID 的线程数比 MAXDOP 多?
他们中的任何一个都正确吗?
我有一个奇怪的情况,我不太明白。
我有一张这样的桌子:
CREATE TABLE dbo.cc_demo
(
id INT IDENTITY PRIMARY KEY,
up_action INT,
down_action INT,
last_action_date DATETIME
);
INSERT dbo.cc_demo ( up_action, down_action, last_action_date )
SELECT TOP 5000000
nums.num % 500000, nums.num % 500000, DATEADD(MINUTE, nums.num, GETDATE())
FROM
( SELECT ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL )) AS num
FROM master..spt_values AS sv
CROSS JOIN master..spt_values AS sv2 ) AS nums;
Run Code Online (Sandbox Code Playgroud)
如果我运行这个查询,该计划只是一个常规的聚集索引扫描。
SELECT *
FROM dbo.cc_demo AS cd
WHERE cd.last_action_date >= '20270601'
AND cd.last_action_date < '20270901';
Run Code Online (Sandbox Code Playgroud)
但是如果我添加一个计算列并索引它,我的计划会发生最坏的变化。
ALTER …Run Code Online (Sandbox Code Playgroud) 在这里继续我的另一个问题,我想要一种简单的方法来形象化答案。
我试过使用这样的查询,但“运行”线程的数量有时会超过 DOP。
SELECT ost.session_id,
ost.exec_context_id,
ost.scheduler_id,
qp.node_id,
w.worker_address,
qp.physical_operator_name,
ost.task_state,
qp.row_count
FROM sys.dm_os_tasks AS ost
JOIN sys.dm_os_workers AS w
ON ost.worker_address = w.worker_address
LEFT JOIN sys.dm_exec_query_profiles AS qp
ON w.task_address = qp.task_address
WHERE ost.session_id = 57
AND ost.task_state = 'RUNNING'
ORDER BY ost.exec_context_id, ost.scheduler_id, qp.node_id, w.worker_address;
Run Code Online (Sandbox Code Playgroud)
我也尝试过使用query_thread_profile扩展事件,但是对于具有多个并行分支的计划,它显示了相同的 N 个线程 ID。这似乎与给出的答案相反,因为 DOP 没有明确限制使用的线程总数。对于以 DOP 4 运行的查询,它看起来像这样。我确信相同的四个线程(加上协调器)不会用于所有分支和运算符。
因此,在 DOP 8 上运行这样的查询会给我三个并行分支。
SELECT COUNT(DISTINCT t1.Data)
FROM dbo.t1
JOIN dbo.t2
ON t1.Id = t2.f_Id
JOIN t3
ON …Run Code Online (Sandbox Code Playgroud)