我在几个存储过程中需要一个相当大的查询,我想将它转换为 UDF 以使其更易于维护(视图不起作用,这需要一堆参数),但是每个人我曾经说过,UDF 的速度非常慢。
虽然我不知道究竟是什么让它们变慢,但我会猜测它们是,但是看到我没有在连接中使用这个 UDF,而是返回一个表变量,我认为它不会会那么糟糕。
所以我想问题是,我应该不惜一切代价避免UDF吗?谁能指出具体的证据表明它们速度较慢?
我在几个存储过程中需要一个相当大的查询,我想将它转换为 UDF 以使其更易于维护(视图不起作用,这需要一堆参数),但是每个人我曾经说过,UDF 的速度非常慢。
虽然我不知道究竟是什么让它们变慢,但我会猜测它们是,但是看到我没有在连接中使用这个 UDF,而是返回一个表变量,我认为它不会会那么糟糕。
所以我想问题是,我应该不惜一切代价避免UDF吗?谁能指出具体的证据表明它们速度较慢?
正如您所指出的,(表)udf 的结果不会与任何东西相连,那么就不应该对性能产生任何影响。
为了解释一下为什么 UDF 会被认为很慢(实际上只是以错误的方式使用),请考虑以下示例;
我们有表 A 和表 B。假设我们有一个像这样的连接
从 A.aid = b.fk_aid 的 A JOIN B 中选择 A.col1、A.col2、B.ColWhatever B.someCol = @param1 AND A.anotherCol = @param2
在这种情况下,SQL Server 将尽最大努力以它知道的最高效的方式返回结果。其中一个主要因素是减少磁盘读取。所以 - 它将使用 JOIN 和 where 子句中的条件来评估(希望使用索引)返回多少行。
现在 - 假设我们提取了一些用于限制返回到 UDF 的数据量的条件。现在 - 查询优化器不能再从磁盘拉回最小数量的行,它只能处理它提供的条件。简而言之 - 始终评估表 udf 并在返回到主 sproc 之前返回数据,因此,如果原始连接中有一些其他条件可能导致更少的磁盘读取 - 这将仅适用于数据在被拉入存储过程之后。
假设我们创建一个 UDF 来从表 B 中选择与 where 子句匹配的行。如果表 B 中有 100k 行并且其中 50% 符合 where 子句的条件 - 那么所有这些行都将返回到存储过程以与表 A 进行比较。现在如果现在只有 10% 的行在表 A 中有匹配项我们只讨论了我们想要使用的表 B 的 5%,但我们已经撤回了 50%,其中大部分是我们不想要的!
如果这完全是胡言乱语的道歉 - 请告诉我!
你能发布你的代码吗?一般来说,如果您在查询的 select 子句中使用标量 udf,则 udf 中的语句将在查询返回的每一行中执行一次。最好对一个值为 udf 的表执行连接,或者找到某种方法在主 SQL 语句中使用连接来执行 udf 中的逻辑。
是否有某些原因您不想使用存储过程而不是 UDF?