有没有一种方法可以防止计算列中的标量UDF抑制并行性?


29

关于SQL Server 中标量UDF危害,已经写了很多文章。随意搜索将返回大量结果。

但是,在某些地方,标量UDF是唯一的选择。

例如:在处理XML时:XQuery不能用作计算列定义。Microsoft记录的一个选项是使用Scalar UDF将XQuery封装在Scalar UDF中,然后在计算列中使用它。

这会产生各种影响,并有一些解决方法。

  • 查询表时逐行执行
  • 强制对表的所有查询顺序运行

您可以通过模式绑定该函数并持久保存计算的列或对其进行索引来解决逐行执行的问题。即使没有引用标量UDF,这两种方法都无法防止查询的强制序列化。

有已知的方法吗?

Answers:


31

是的,如果您:

  • 正在运行SQL Server 2014或更高版本;和
  • 能够在跟踪标记176处于活动状态的情况下运行查询;和
  • 计算列是 PERSISTED

具体来说,至少需要以下版本:

  • SQL Server 2016 SP1的累积更新2
  • SQL Server 2016 RTM的累积更新4
  • SQL Server 2014 SP2的累积更新6

为了避免错误(用于REF 2014,以及2016和2017年),在这些补丁推出,而是适用于:

使用,跟踪标记–T在全局和会话范围内均有效,可作为启动选项DBCC TRACEON,并且每个查询使用OPTION (QUERYTRACEON)或计划指南。

跟踪标记176防止持久的计算列扩展。

编译查询时执行的初始元数据加载会引入所有列,而不仅仅是直接引用的那些列。这使得所有计算的列定义都可用于匹配,这通常是一件好事。

作为不幸的副作用,如果已加载(计算的)列之一使用标量用户定义函数,则即使实际未使用计算列,其存在也会对整个查询禁用并行性

如果该列被保留,则跟踪标志176通过不加载定义(因为扩展被跳过)而对此有所帮助。这样,标量用户定义函数永远不会出现在编译查询树中,因此不会禁用并行性。

跟踪标志176的主要缺点(除了仅作简单记录外)还阻止查询表达式与持久化的计算列匹配:如果查询包含与持久化的计算列匹配的表达式,跟踪标志176将阻止表达式替换为对计算列的引用。

有关更多详细信息,请参见我的SQLPerformance.com文章“ 正确地保留计算列”

由于问题提到XML,作为使用计算列和标量函数提升值的替代方法,因此您也可以考虑使用Selective XML Index,如您在Selective XML Indexes:All Bad All中所写。


10

除了@Paul出色的Yes#1之外,实际上还有一个Yes#2:

  • 可以追溯到SQL Server 2005
  • 不需要设置跟踪标志,
  • 要求计算列是PERSISTED,和
  • (由于不需要跟踪标志176),并不能防止查询表达式匹配到持续计算列

(据我所知)唯一的缺点是:

  • 不能在Azure SQL数据库上运行(至少还不能,尽管它在Amazon RDS SQL Server以及Linux上的SQL Server上都可以运行),并且
  • 在许多DBA的舒适区之外

并且此选项是:SQLCLR

那就对了。SQLCLR标量UDF的一个很酷的方面是,如果它们不进行任何数据访问(用户和系统都没有),那么它们就不会禁止并行性。这不只是理论或市场营销。尽管我目前没有时间进行详细的撰写,但我已经测试并证明了这一点。

我使用了以下博客文章中的初始设置(希望OP不会认为这是不可靠的来源):

坏主意牛仔裤:多种索引提示

并进行了以下测试:

  1. 照原样运行初始查询─⇾并行性(符合预期)
  2. 添加了一个非持久的计算列,定义为([c2] * [c3])─并行性(符合预期)
  3. 移除了计算列,并增加了非持续计算列中引用的T-SQL标量UDF(以创建SCHEMABINDING定义为)RETURN (@First * @Second);─⇾NO平行(如预期)
  4. 除去T-SQL UDF计算列,并增加了非持续计算列中引用的标量SQLCLR UDF(试图用两者IsDeterministic = true= false)定义为return SqlInt32.Multiply(First, Second);─⇾ 并行(宇豪!!)

因此,尽管SQLCLR并非对每个人都适用,但对于那些非常适合的人/情况/环境,它无疑具有优势。并且,由于涉及到这个特定的问题(使用XQuery的示例),它可以为此工作(并且,具体取决于正在执行的操作,它甚至可能更快一点)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.