相当有据可查的是,标量UDF强制执行总体串行计划。
鉴于大量行进入必须计算UDF的管道中的某个点,为什么引擎不能只在处理器之间分配它们呢?如果UDF中没有状态,则顺序无关紧要。
有人声称UDF是黑匣子,必须使用游标。我可以看到,在两次迭代之间保持某种状态的情况下,用户游标无法在SP内并行化,但是看起来应该可以并行化。
解释引擎为何强制整个计划按顺序进行而不是仅由UDF计算阶段进行的加分。
对并行UDF的支持是否是要求的合理功能?
相当有据可查的是,标量UDF强制执行总体串行计划。
鉴于大量行进入必须计算UDF的管道中的某个点,为什么引擎不能只在处理器之间分配它们呢?如果UDF中没有状态,则顺序无关紧要。
有人声称UDF是黑匣子,必须使用游标。我可以看到,在两次迭代之间保持某种状态的情况下,用户游标无法在SP内并行化,但是看起来应该可以并行化。
解释引擎为何强制整个计划按顺序进行而不是仅由UDF计算阶段进行的加分。
对并行UDF的支持是否是要求的合理功能?
Answers:
相当有据可查的是,UDF强制执行总体序列计划。
我不确定文件是否全部记录在案。
请参阅强制执行并行执行计划和/或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中实现。
正如Paul在其回答中正确提到的那样,没有根本的原因无法使用并行性执行标量UDF。但是,除了实现方面的挑战外,还有其他原因迫使它们必须串行化。保罗引用的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论文的合著者]