Wor*_*SQL 7 sql-server parallelism
我和一个非常老的 DBA 一起工作,他说了很多奇怪的话。Dude 有一本 O'Reilly 的书,封面上只有一个变形虫。
午餐时我们讨论了并行性,因为我们的新服务器有 24 个内核。他说,在并行计划中,每个操作员都会获得 DOP 线程。因此,如果您有 MAXDOP 8 并且您的查询有 4 个并行运算符,它将一次使用 32 个线程。
这似乎不对,因为您会很快用完线程。
我还读到整个查询可能只有 8 个,这似乎太少了。
为什么我在 sysprocesses 中看到每个 SPID 的线程数比 MAXDOP 多?
他们中的任何一个都正确吗?
Pau*_*ite 15
他说,在并行计划中,每个操作员都会获得 DOP 线程。
不。这充其量只是误导,但更接近于完全错误。
在串行计划中,每个操作员“获得”一个线程,但该线程对于所有操作员来说都是同一个线程。并行计划的原理类似。
每个并行运算符都由 DOP线程运行,但这些线程并不专属于特定的运算符,它们在同一并行分支内的运算符之间共享。
分支边界由并行操作符(Demand、Repartition 和 Gather Streams)定界。下图显示了具有三个分支的并行计划:
因此,如果您有
MAXDOP 8并且您的查询有 4 个并行运算符,它将一次使用 32 个线程。
没有。您不能仅乘以DOP运算符的数量来获得线程数。为并行分支保留的线程数是并行分支(不是运算符)的数量乘以DOP。
DOP在SQL Server 2005 和更高版本中,单个并行查询可以同时处于活动状态的线程数限制为。SQL Server 通过将线程分配给DOP调度程序来实现这一点。
我还读到整个查询可能只有 8 个,这似乎太少了。
在DOP = 8这将是一个单一的并联支路计划是正确的。一个并行计划中可以有多个并行计划分支。对于具有n并行分支的计划,并行工作程序的线程预留为n * DOP。
请参阅Paul White 的并行执行计划 – 分支和线程。
注意:执行计划中报告的分支数通常是可能并发执行的分支数(由于阻塞运算符,一个分支中的线程有时可能会被安全地回收到后面的分支)。
我所有的生产机器都在 SQL Server 2008(甚至不是 R2)上,而且没有钱升级。但我得到了一个管理层不知道的 3 CPU 虚拟机,其中隐藏着 SQL Server 2017 开发人员版(它是免费的!)。我对此做了测试。
本周早些时候,我们的一位开发人员编写了很多 CROSS JOIN 查询,它们引起了一些问题,但我可以使用类似的查询来主要回答这个问题。开发者做了这样的事情:
SELECT MIN(t1.high + t2.high)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
OPTION (MAXDOP 3);
Run Code Online (Sandbox Code Playgroud)
就像我说的,这个查询引起了各种警告警报,我不得不在半夜醒来。以下是我的 2017 年“实例”上的查询计划:
所以我有五个带有赛车箭头的操作员,这首先让我认为计划中有 5 个并行的操作员。但 SQL Server 可能会很棘手。嵌套循环连接实际上是一个并行运算符,因此总共有 6 个并行运算符。如果查询 MAXDOP 为 3,如果它按照问题中描述的方式工作,我将得到 3 * 6 = 18 个工作人员。我可以在实际计划的 XML 中查找以下内容:
<QueryPlan DegreeOfParallelism="3" MemoryGrant="56" CachedPlanSize="32" CompileTime="3" CompileCPU="3" CompileMemory="272">
<ThreadStat Branches="1" UsedThreads="3">
<ThreadReservation NodeId="0" ReservedThreads="3" />
</ThreadStat>
Run Code Online (Sandbox Code Playgroud)
这使得查询执行期间看起来只使用了 3 个线程。另外,我从互联网上获取了此查询,并在执行 CROSS JOIN 查询时运行它:
SELECT *
FROM sys.dm_os_tasks d
INNER JOIN sys.dm_exec_sessions s ON d.session_id = s.session_id
WHERE s.is_user_process = 1 AND s.session_id <> @@SPID;
Run Code Online (Sandbox Code Playgroud)
它仅显示 exec_context_id 值在 0 到 3 之间的四行。因此,即使有许多并行运算符,该查询也仅使用了三个并行工作线程。确实,更复杂的查询可以使用比 MAXDOP 更多的工作线程,但我认为可以肯定地说,查询不会为每个并行运算符获取 MAXDOP 工作线程。
更新:
我在互联网上找到了一个跟踪标志(不要在生产中使用!)并用它来获取另一个并行计划:
那一个有六个并行工作线程!所以看起来不同模式的查询确实可以获得不同的工作线程,但它仍然不是每个运算符的 MAXDOP 线程。