从参数创建局部变量可提高sproc性能

时间:2014-05-26 06:18:03

标签: sql-server variables stored-procedures

我有一个相对简单的存储过程,用于在相对讨厌的视图中对数据进行分组,我无法根据提供的参数进行控制。存储过程的简化版本是:

CREATE PROCEDURE dbo.GroupList 
    @list VARCHAR(MAX), 
    @start DATETIME, 
    @end DATETIME,
    @resolution INT
AS
BEGIN  
    SET NOCOUNT ON

    declare @elements ListTVP;
    insert into @elements select Value as elementID from udf_Split(@localList, ',');

    IF @resolution = 1  -- group by month
    BEGIN
        SELECT *
        FROM (
            SELECT
                Timestamp = CAST(CONVERT(VARCHAR, DATEPART(YEAR, Timestamp)) + '-' + CONVERT(VARCHAR, DATEPART(MONTH, Timestamp)) + '-01' AS DATETIME)
                , Total = SUM(Cost)
            FROM eLP e
                INNER JOIN @elements m ON e.elementID = m.elementID
            WHERE Timestamp >= @start AND Timestamp <= @end
            GROUP BY 
                DATEPART(YEAR, Timestamp),
                DATEPART(MONTH, Timestamp)
            ) AS t1
    END
    ELSE IF @resolution = 2 -- group by year
    BEGIN
        SELECT *
        FROM (
            SELECT
                Timestamp = CAST(CONVERT(VARCHAR, DATEPART(YEAR, Timestamp)) + '-01-01' AS DATETIME)
                , Total = SUM(Cost)
            FROM eLP e
                INNER JOIN @elements m ON e.elementID = m.elementID
            WHERE Timestamp >= @start AND Timestamp <= @end
            GROUP BY 
                DATEPART(YEAR, Timestamp)
            ) AS t1
    END
END

如果我在SSMS内的存储过程中运行SQL代码,代码相对较快。如果我运行存储过程,则对于完全相同的数据,代码的速度会慢10至100倍。为什么会这样?

另外,我注意到如果我从提供的参数创建局部变量,性能会大幅提升:

CREATE PROCEDURE dbo.GroupListWithVariables
    @list VARCHAR(MAX), 
    @start DATETIME, 
    @end DATETIME,
    @resolution INT
AS
BEGIN
    DECLARE @localList VARCHAR(MAX) = @list
    DECLARE @localStart DATETIME = @start, @localEnd DATETIME = @end
    DECLARE @localResolution INT = @resolution

比较存储过程的两个版本的执行时间,我有:

  • 群组列表:
    • 平均执行时间568毫秒
    • SSMS报告9秒实际运行sproc并检索结果
    • 355 kB从服务器收到的数据
  • GroupListWithVariables:
    • 平均执行时间1040毫秒
    • SSMS报告1秒实际运行sproc并检索结果
    • 从服务器收到的239 kB数据

为什么两个版本之间存在如此大的差异?我在SQL Server 2008 R2以及SQL Server 2012中都注意到了相同的行为。

1 个答案:

答案 0 :(得分:1)

您可能想要了解SQL参数嗅探。 http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx

这可能有助于解释性能差异。