SQLServer:为什么要避免使用表值的用户定义函数?

时间:2009-07-03 22:44:33

标签: sql-server user-defined-functions

我有一个相当庞大的查询,在几个存储过程中需要,我想将它转换为UDF以使其更容易维护(视图将无法工作,这需要一堆参数)但是,我曾与之交谈过的每个人都告诉我,UDF非常慢。

虽然我不知道究竟是什么让它们变慢,但我会猜测它们是,但看到我在连接中没有使用这个UDF,而是返回一个表变量,我认为它不会那么糟糕。

所以我想问题是,我应该不惜一切代价避免使用UDF吗?任何人都可以指出具体证据表明它们较慢吗?

4 个答案:

答案 0 :(得分:4)

标量UDF非常慢,内联UDF实际上是宏,因此它们非常快: 一些文章:

Reuse Your Code with Table-Valued UDFs

Many nested inline UDFs are very fast

关于标量UDF缓慢的更多链接:

SQL Server Performance patterns of a UDF with datetime parameters

Not all UDFs are bad for performance

答案 1 :(得分:3)

正如你所指出的那样,(表)udf的结果不会被加入任何东西,那么对性能没有任何影响。

试着解释为什么UDF可以被认为是缓慢的(实际上只是以错误的方式使用),请考虑以下例子;

我们有表A和表B.假设我们有一个像

这样的连接

选择     A.col1,     A.col2,     B.ColWhatever 从         一个 JOIN B ON A.aid = b.fk_aid 哪里     B.someCol = @ param1 AND A.anotherCol = @ param2

在这种情况下,SQL Server最好以其知道的最高性能方式返回结果。这方面的一个主要因素是减少磁盘读取。所以 - 它将使用JOIN和where子句中的条件来评估(希望有一个索引)要返回的行数。

现在 - 假设我们提取了一些用于重新生成返回UDF的数据量的条件。现在 - 查询优化器不能再从磁盘中撤回最少量的行,它只能处理它提供的条件。简而言之 - 表udf总是被评估,并且数据在返回到主sproc之前返回,因此,如果原始连接中存在可能导致更少磁盘读取的某些其他条件 - 这将仅应用于数据被拉入sproc后。

所以说我们创建一个UDF来从表B中选择与where子句匹配的行。如果表B中有100k行,并且其中50%满足where子句的条件 - 则所有这些行都将返回到sproc以与表A进行比较。现在,如果只有10%的行在表A中具有匹配项我们只讨论了我们想要合作的B表的5%,但是我们已经退回了50%,其中大部分是我们不想要的!

如果这是完全的胡言乱语 - 请告诉我!

答案 2 :(得分:0)

你能发布你的代码吗?一般来说,如果在查询的select子句中使用标量udf,则udf中的语句将从查询返回的每行执行一次。最好是对值为udf的表执行连接,或者在主SQL语句中使用连接找到一些在udf中执行逻辑的方法。

答案 3 :(得分:-2)

是否有某些原因您不想使用stored procedure而不是UDF?

相关问题