【问题标题】:Why SQL functions are faster than UDF为什么 SQL 函数比 UDF 快
【发布时间】:2013-11-21 22:38:32
【问题描述】:

虽然这是一个相当主观的问题,但我觉得有必要在这个论坛上分享。

我亲身经历过,当我创建一个 UDF(即使这并不复杂)并将其用于我的 SQL 时,它会大大降低性能。但是当我使用SQL inbuild function 时,它们的工作速度会更快。转换、逻辑和字符串函数就是一个明显的例子。

所以,我的问题是“为什么构建函数中的 SQL 比 UDF 更快”?如果有人可以指导我如何从数学或逻辑上判断/操纵函数成本,那将是一个优势。

【问题讨论】:

  • “用户定义函数”是什么意思?您是指使用CREATE FUNCTION 创建的函数,还是用 C 或 C++ 编写并动态包含或在编译时包含的函数?
  • 许多内置函数在查询计划中被实现为特殊运算符(例如,标准聚合器或窗口函数),或者足够简单以至于它们无论如何都不会变慢。

标签: sql-server tsql user-defined-functions


【解决方案1】:

这是 SQL Server 中标量 UDF 的一个众所周知的问题。

它们没有内联到计划中,与具有相同的内联逻辑相比,调用它们会增加开销。

以下在我的机器上只需要不到 2 秒的时间

WITH T10(N) AS 
(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
) --10 rows                                    
, T(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
           FROM T10 a, T10 b, T10 c, T10 d, T10 e, T10 f, T10 g)  -- 10 million rows
SELECT MAX(N - N)
FROM T
OPTION (MAXDOP 1)

创建简单的标量 UDF

CREATE FUNCTION dbo.F1 (@N BIGINT)
RETURNS BIGINT 
WITH SCHEMABINDING
AS
BEGIN
RETURN (@N - @N)
END

将查询更改为MAX(dbo.F1(N)) 而不是MAX(N - N)STATISTICS TIME OFF 需要大约 26 秒,而启用它需要 37 秒。

1000 万次函数调用平均增加 2.6μs / 3.7μs。

运行 Visual Studio 分析器显示绝大多数时间都在 UDFInvoke 下进行。调用堆栈中的方法名称给出了额外开销在做什么(复制参数、执行语句、设置安全上下文)的一些概念。

将逻辑移入内联表值函数

CREATE FUNCTION dbo.F2 (@N BIGINT)
RETURNS TABLE
RETURN(SELECT @N - @N AS X)

并将查询重写为

SELECT MAX(X)
FROM Nums
CROSS APPLY dbo.F2(N)

执行速度与不使用任何函数的原始查询一样快。

【讨论】:

    猜你喜欢
    • 2018-04-29
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 2018-10-05
    • 2012-08-24
    • 2019-11-02
    • 2013-12-16
    • 2019-09-30
    相关资源
    最近更新 更多