我有一个相对简单的存储过程,用于在相对讨厌的视图中对数据进行分组,我无法根据提供的参数进行控制。存储过程的简化版本是:
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
比较存储过程的两个版本的执行时间,我有:
为什么两个版本之间存在如此大的差异?我在SQL Server 2008 R2以及SQL Server 2012中都注意到了相同的行为。
答案 0 :(得分:1)
您可能想要了解SQL参数嗅探。 http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx
这可能有助于解释性能差异。