为什么SQL函数比UDF更快

时间:2013-11-09 22:53:50

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

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

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

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

1 个答案:

答案 0 :(得分:3)

这是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下进行。调用堆栈中方法的名称可以让您了解额外开销正在做什么(复制参数,执行语句,设置安全上下文)。

enter image description here

将逻辑移动到内联表值函数

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

将查询重写为

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

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