循环与需求并行分区

Gok*_*han 8 sql-server parallelism partitioning

这与在带有嵌套循环的查询之上有一个公共密钥驱动程序有关,并且来自驱动程序的行的并行性是需求类型或循环类型。我会假设需求分区会表现得更好,但我得到了相反的结果。

我在 SQL Server 中的同一次尝试中同时启动了查询。当我监控的查询运行时dm_exec_query_profilesdmv 不断。我注意到循环版本的启动速度要快得多,它们在 dmv 的表插入部分中插入更多行的速度要快得多,而且它们从驱动程序侧并行性部分更快地获取更多行。从逻辑上思考需求分区应该更有利,因为我们的 SQL 服务器通常超过 50-60% 的 cpu,运行 litespeed 备份,有 64 个内核等。我能够通过循环分区更好地平衡线程上处理的行,还有数据分区内是如此不平衡我注意到需求分区中的一些线程仅处理来自驱动程序的 1 条记录,而来自驱动程序的平均记录大约为 196。通过需求分区,我对分区内的行进行降序排序,而在循环中我尝试更好地平衡行。

我是否应该始终使用循环法,为什么循环法开始处理行的速度比需求分区快得多,我可以对需求分区进行更多优化吗?

查询计划位于 One Drive 链接中,我找不到在此处发布它们的另一种方式(pastetheplan 仅接受 xml,它不捕获计划资源管理器捕获的等待统计信息和持续时间等额外信息)。


CompareRoundRobinToDemand_DM_2_5114.pesession CompareRoundRobinToDemand_RRB_2_3046.pesession

同时开始,Round Robin 的速度要快得多


CompareRoundRobinToDemand_DM_3_5228.pesession CompareRoundRobinToDemand_RRB_3_4367.pesession

同时开始,Round Robin 又快了


CompareRoundRobinToDemand_DM_4_4813.pesession CompareRoundRobinToDemand_RRB_4_3577.pesession

同时开始,Round Robin 又快了

先感谢您。

监控运行会话 查询计划

SQL Server 版本和运行跟踪

我能够平衡几乎完美的循环行,而对于需求,我只是按行降序排列驱动程序,平衡需求中的行是我的程序中的一个选项,但没有产生更好的结果。在我的观察中,当整体 CPU 使用率较低时,需求表现更好,而当服务器更忙时,轮询表现更好。我注意到与循环相比,需求创建了一个额外的线程,而且总体 CPU 利用率需求略高于类似的 RRB 版本。

我知道需求中的行分布不平衡。内存授予也是故意的,它最终没有使用那么多内存。从驱动程序传递的前 16 条记录的需求与循环法相同,但循环法由于某种原因开始处理它们的速度要快得多。我想明白为什么。我还想了解什么时候使用需求或循环法更有利。似乎当服务器空闲时需求工作得更快,当服务器有现有负载时循环更快,这是迄今为止的观察,这是否有我不知道的基础。

Pau*_*ite 8

我应该总是使用循环法吗

只有当您发现它为您的特定工作负载或该工作负载中的特定查询产生“更好”的结果时。

一般来说,我会说不。我个人的经验是,需求 (D) 分区往往比循环 (RR) 出现更少的问题。您分享的特定计划似乎没有任何可能导致 RR 性能问题的更常见的功能,但很难远距离评估。

为什么循环开始处理行的速度比需求分区快得多

如果我冒险猜测,我会说 D 分区线程更频繁地检查和让出处理器。平均使用较少量的线程(通过更频繁地检查和让步)是一个很好的调度公民,但它可能会因这种良好行为受到惩罚(在 SQL Server 2016 之前)。您分享的屏幕截图似乎确实显示 D 计划获得的 CPU 时间少于并发 RR 执行。

D 在整个交换中拉单行,而 RR 推送整个数据包 - 并且在交换中(以及许多其他地方)进行产量检查。需要非常详细的分析来证实这个(或任何其他)理论。

我可以对需求分区做更多优化吗?

从我所见,该计划似乎足够合理。

有趣的是,屏幕截图显示了合并连接,而上传的计划都使用哈希连接。尝试同地合并连接是我想到的第一个建议 - 正如我的文章提高分区表连接性能 中所述

您还可以检查跨调度程序的线程分布,并可能尝试不同的线程放置策略。我肯定会检查 D 计划是否像 RR 版本一样最佳地分配线程(例如,没有并发的同一分支线程共享相同的调度程序)。

也许还可以看看以不同的顺序呈现需求行。您现在拥有的可能基于合理的期望,但这并不是说它一定是最佳的。

在任何情况下,我都会非常谨慎地根据这个例子得出关于 D 与 RR 的一般性结论。


我注意到与循环法相比,需求创造了一个额外的线程

由于时间差异,这是一种错觉。在 RR 计划中,索引扫描完成得非常快,它的行被塞进交换机的数据包中。运行扫描的线程因此迅速终止。

在 D 计划中,各个行在交换中按需拉出,并在拉出新行之前进行了充分处理。因此,Constant Scan 线程会停留更长时间。

两个计划都有两个并发分支,每个分支都保留了 DOP (16) 个线程。两者都使用ThreadStatshowplan 元素中报告的 17 个线程(16 个用于主分支,1 个用于串行索引扫描/常量扫描)。


Joe*_*ish 6

从逻辑上思考需求分区应该更有利,因为我们的 SQL 服务器通常超过 50-60% cpu,运行 litespeed 备份,有 64 个内核等。

我不能完全跟着你在这里。也许您认为需求分配会更有效,因为如果您使用循环分区,其中一个线程可能会“卡住”?在繁忙的服务器上,您的线程将执行少量工作,因为它们能够这样做。如果您有 64 个内核并且服务器使用大约 60% 的 CPU,这是否意味着您有足够的空间让 16 个线程上的循环分区正常工作?

以下是序列项目中循环计划 (CompareRoundRobinToDemand_DM_2_5114.psession) 的行分布:

循环赛

所有运算符的行分布都非常均匀。如果您尝试优化查询以尽可能减少时间并且没有任何线程最终处于完全超载的调度程序上,那么这是一件好事。如果一个线程分配了太多行,那么查询可能最终会等待最后一个线程完成其工作。

这是需求查询的行分布 (CompareRoundRobinToDemand_DM_2_5114.pesession):

要求

您的某些线程处理的行数是其他线程的 8 倍。如果您需要尽快完成查询,这不是您想要看到的。这并不意味着根据服务器工作负载,这种结果并不比循环分区好,但在这种情况下,您似乎没有从需求分布中受益。

在一个不相关的说明中,我会注意这个警告:

查询内存授予检测到“ExcessiveGrant”,这可能会影响可靠性。授权大小:初始 288185664 KB,最终 288185664 KB,已用 9726112 KB。

当这两个查询运行时,您将迫使 SQL Server 专用于 576 GB 的内存,其中大部分未被使用。在可能导致其他进程出现问题的非常繁忙的服务器上。