有没有办法防止计算列中的标量 UDF 抑制并行性?

Eri*_*ing 31 sql-server parallelism functions computed-column

已经有很多关于SQL Server中标量 UDF危险的文章。随意搜索将返回大量结果。

不过,有些地方标量 UDF 是唯一的选择。

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

这会产生各种影响和一些解决方法。

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

您可以通过对函数进行架构绑定来绕过逐行执行,并保留计算列或对其进行索引。即使未引用标量 UDF,这两种方法都不能阻止强制序列化查询表。

有没有一种已知的方法可以做到这一点?

Pau*_*ite 33

是的,如果您:

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

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

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

但是为了避免这些修复中引入的错误(参考2014 年,以及2016 年和 2017 年),改为应用:

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

跟踪标志 176 可防止持久计算列扩展。

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

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

跟踪标志 176 通过不加载定义(因为跳过扩展)来帮助解决此问题,如果该列被持久化。这样,编译查询树中永远不会出现标量用户定义函数,因此不会禁用并行性。

跟踪标志 176 的主要缺点(除了只是很少记录)还阻止查询表达式匹配持久计算列:如果查询包含匹配持久计算列的表达式,跟踪标志 176 将阻止表达式被替换为对计算列的引用。

有关更多详细信息,请参阅我的 SQLPerformance.com 文章正确持久化计算列

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


Sol*_*zky 12

除了@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. 删除了该计算列并添加了一个非持久计算列,该列引用了SCHEMABINDING定义为RETURN (@First * @Second);?? 无并行性(如预期)
  4. 除去T-SQL UDF计算列和添加的非持久化计算列中引用的标量SQLCLR UDF(与两个尝试IsDeterministic = true= false定义为)return SqlInt32.Multiply(First, Second);?? 平行性(呜呜!!)

因此,虽然 SQLCLR 并不适用于所有人,但它对于那些非常适合的人/情况/环境肯定有其优势。并且,由于它与这个特定问题有关——给出的示例是关于使用 XQuery 的——它肯定会为此起作用(并且,取决于具体正在做什么,它甚至可能更快一点)。