对并行标量 UDF 的支持是一个合理的功能请求吗?

cro*_*sek 10 sql-server parallelism functions

标量 UDF 强制执行整体串行计划,这是有据可查的。

并行运行函数

给定大量行进入管道中必须计算 UDF 的点,为什么引擎不能将它们分配给处理器?如果 UDF 中没有状态,那么顺序应该无关紧要。

有人声称 UDF 是一个必须使用光标的黑匣子。我可以看到,对于在迭代之间维护某些状态但似乎应该可以并行化的情况,用户游标无法在 SP 中并行化。

解释为什么引擎强制整个计划是串行的,而不仅仅是 UDF 计算阶段的额外要点。

对并行 UDF 的支持是一个合理的要求吗?

Pau*_*ite 17

UDF 强制执行整体串行计划是有据可查的。

我不确定这一切是否有据可查。

  • 标量 T-SQL 函数可防止计划中任何地方的并行性。
  • 标量 CLR 函数可以并行执行,只要它不访问数据库。
  • 多语句表值 T-SQL 函数强制计划中的串行区域可能在其他地方使用并行性。
  • 内联表值 T-SQL 函数像视图一样展开,因此没有直接影响。

请参阅强制并行执行计划和/或 Craig Freedman 的并行执行演示

有人声称 UDF 是一个必须使用光标的黑匣子。

这些说法是不正确的。

解释为什么引擎强制整个计划是串行的,而不仅仅是 UDF 计算阶段的额外要点。

我的理解是,当前的限制纯粹是某些实施细节的结果。无法使用并行性执行函数没有根本原因。

具体来说,T-SQL 标量函数在单独的 T-SQL 上下文中执行,这使正确的操作、协调和关闭(尤其是在出现错误的情况下)显着复杂化。

同样,表变量通常确实支持并行读取(但不支持写入),但是由于特定于实现的原因,表值函数公开的表变量不能支持并行读取。恐怕您需要具有源代码访问权限(以及共享详细信息的自由)的人来提供权威答案。

对并行 UDF 的支持是一个合理的要求吗?

当然,如果你能做出足够强大的案例。我自己的感觉是涉及的工作会很广泛,所以你的提案必须达到极高的标准。例如,提供内联标量函数的相关(并且更简单)请求得到了很大的支持,但多年来一直没有实现。


您可能喜欢阅读 Microsoft 论文:

...其中概述了 Microsoft 在 SQL Server 2017 之后的版本中解决 T-SQL 标量函数性能问题的方法。

Froid 的目标是使开发人员能够在不影响性能的情况下使用 UDF 和过程的抽象。Froid 使用一种新技术来实现这一目标,只要有可能,它就会自动将命令式程序转换为等效的关系代数形式。Froid 将命令式代码块建模为关系表达式,并使用 Apply 运算符系统地将它们组合成单个表达式,从而使查询优化器能够选择高效的面向集合的并行查询计划。

(强调我的)


内联标量 T-SQL 函数现在在 SQL Server 2019 中实现


Kar*_*hik 11

正如保罗在他的回答中正确提到的那样,标量 UDF 不能使用并行执行没有根本原因。然而,除了实施挑战之外,还有另一个原因迫使它们是串行的。Paul 引用的Froid论文提供了更多关于此的信息。

引自论文(第 2.3 节):

目前,SQL Server 在调用 UDF 的查询中不使用查询内并行性。可以设计方法来减轻这种限制,但它们会带来额外的挑战,例如为 UDF 的每次调用选择正确的并行度。

例如,考虑一个调用其他 SQL 查询的 UDF,如图 1 中的查询。每个这样的查询本身可能使用并行性,因此,优化器无法知道如何在它们之间共享线程,除非它查看UDF 并决定其中每个查询的并行度(这可能会从一个调用更改为另一个调用)。使用嵌套和递归 UDF,这个问题变得更加难以管理。

如论文中所述,Froid 的方法不仅会产生并行计划,还会为使用 UDF 的查询增加更多好处。实质上,它包含了您对并行执行 UDF 的请求。

更新: Froid 现在作为 SQL Server 2019 预览版的一项功能提供。该功能称为“标量 UDF 内联”。更多细节在这里:https : //blogs.msdn.microsoft.com/sqlserverstorageengine/2018/11/07/introducing-scalar-udf-inlining/

[披露:我是 Froid 论文的合著者]