AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 187342
Accepted
Erik Darling
Erik Darling
Asked: 2017-10-01 08:40:04 +0800 CST2017-10-01 08:40:04 +0800 CST 2017-10-01 08:40:04 +0800 CST

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

  • 772

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

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

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

这有各种影响和一些解决方法。

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

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

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

sql-server functions
  • 2 2 个回答
  • 3098 Views

2 个回答

  • Voted
  1. Best Answer
    Paul White
    2017-10-01T22:21:30+08:002017-10-01T22:21:30+08:00

    是的,如果您:

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

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

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

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

    • SQL Server 2017 的累积更新 1
    • SQL Server 2016 SP1 的累积更新 5
    • SQL Server 2016 RTM 的累积更新 8
    • SQL Server 2014 SP2 的累积更新 8

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

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

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

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

    跟踪标志 176 有助于解决此问题,如果列是持久的,则不加载定义(因为跳过了扩展)。这样,用户定义的标量函数就不会出现在编译查询树中,因此不会禁用并行性。

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

    有关更多详细信息,请参阅我的 SQLPerformance.com 文章Properly Persisted Computed Columns。

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

    • 35
  2. Solomon Rutzky
    2017-10-20T11:55:55+08:002017-10-20T11:55:55+08:00

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

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

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

    • 不适用于 Azure SQL 数据库(至少目前还不能,尽管它确实适用于 Amazon RDS SQL Server 以及 Linux 上的 SQL Server),并且
    • 有点超出许多 DBA 的舒适区

    这个选项是:SQLCLR

    这是正确的。SQLCLR Scalar UDF 的一个很酷的方面是,如果它们不进行任何数据访问(无论是用户还是系统),那么它们就不会禁止并行性。这不仅仅是理论或营销。虽然我(目前)没有时间进行详细的撰写,但我已经测试并证明了这一点。

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

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

    并进行了以下测试:

    1. 按原样运行初始查询 ─⇾ 并行性(如预期的那样)
    2. ([c2] * [c3])添加了定义为─⇾ Parallelism的非持久计算列(如预期的那样)
    3. 删除了该计算列并添加了一个非持久计算列,该列引用了SCHEMABINDING定义为RETURN (@First * @Second);─⇾ NO Parallelism(如预期)的 T-SQL 标量 UDF(使用创建)
    4. 删除了 T-SQL UDF 计算列并添加了一个非持久计算列,该列引用了IsDeterministic = true定义= false为return SqlInt32.Multiply(First, Second);─⇾ Parallelism (woo hoo!!)

    因此,虽然 SQLCLR 并不适用于所有人,但对于那些非常适合的人/情况/环境来说,它肯定有其优势。而且,由于它与这个特定的问题有关——给出的例子是关于使用 XQuery 的——它肯定会为此工作(并且,根据具体所做的工作,它甚至可能会快一点?)。

    • 12

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve