由于内部使用的函数,存储过程执行时间较长

Stored procedure execution taking long because of function used inside

在 SQL Server 2012 中,我有以下用户定义函数:

CREATE FUNCTION [dbo].[udfMaxDateTime]()
RETURNS datetime
AS 
BEGIN 
    RETURN '99991231';
END;

然后将其用于存储过程,如下所示:

DECLARE @MaxDate datetime = dbo.udfMaxDateTime();

DELETE FROM TABLE_NAME
WHERE 
    ValidTo = @MaxDate
AND
    Id NOT IN
    (
        SELECT 
            MAX(Id)
        FROM 
            TABLE_NAME 
        WHERE
            ValidTo = @MaxDate
        GROUP 
        BY 
            COL1
        );

现在,如果我 运行 使用上述代码的存储过程,执行大约需要 12 秒。 (120 万行)

如果我将 WHERE 子句更改为 ValidTo = '99991231' 那么,存储过程 运行s 会在 1 秒内完成 运行s并行。

谁能解释一下为什么会这样?

不是自定义函数的问题,是变量的问题

当您在 DELETE 中使用变量 @MaxDate 时,查询优化器在生成执行计划时不知道该变量的值。因此,当您在查询中进行相等比较时,它会根据 ValidTo 列上的可用统计信息和一些用于基数估计的内置启发式规则生成计划。

当您在查询中使用文字常量时,优化器知道它的值并可以生成更有效的计划。

如果您添加 OPTION(RECOMPILE),执行计划将不会被缓存,并且会始终重新生成,并且所有参数值都会为优化器所知。使用此选项查询很可能 运行 很快。此选项确实会增加一定的开销,但只有当您经常 运行 查询时才会注意到这一点。

DECLARE @MaxDate datetime = dbo.udfMaxDateTime();

DELETE FROM TABLE_NAME
WHERE 
    ValidTo = @MaxDate
AND
    Id NOT IN
    (
        SELECT 
            MAX(Id)
        FROM 
            TABLE_NAME 
        WHERE
            ValidTo = @MaxDate
        GROUP BY 
            COL1
    )
OPTION(RECOMPILE);

我强烈推荐阅读 Erland Sommarskog 的 Slow in the Application, Fast in SSMS