静态查询与存储过程的性能问题

时间:2015-04-20 17:48:24

标签: performance sql-server-2008 stored-procedures

我有两个几乎相同的查询,第一个是带有变量的静态查询,第二个是带有输入参数的存储过程。

静态查询

DECLARE @GLNumber INT = 1043
DECLARE @StartDate DATE = '1/1/2015'
DECLARE @EndDate DATE = '4/20/2015'

    SELECT 
        T1.EMPLOYEE         AS [Empolyee Number],
        T2.LAST_NAME        AS [Last Name],
        T2.FIRST_NAME       AS [First Name],
        T1.DST_ACCT_UNIT    AS [Distribution Account Unit],
        T3.DESCRIPTION,
        SUM(T1.WAGE_AMOUNT) AS [Wage Amount]    
    FROM 
        JOBCODE T3, 
        EMPLOYEE T2 LEFT OUTER JOIN 
        PRTIME T1 ON 
            T2.COMPANY = T1.COMPANY and 
            T2.EMPLOYEE = T1.EMPLOYEE
    WHERE 
        T1.DIST_COMPANY = @GLNumber and 
        CONVERT(DATE, TR_DATE, 101) BETWEEN @StartDate AND @EndDate AND
        T1.PAY_SUM_GRP in ('TPC', 'TDS') and 
        T2.JOB_CODE = T3.JOB_CODE and 
        T2.COMPANY = T3.COMPANY
    GROUP BY
        T1.EMPLOYEE,
        T2.LAST_NAME,
        T2.FIRST_NAME,
        T1.DST_ACCT_UNIT,
        T3.DESCRIPTION

存储过程

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[MySproc]
(
    @GLNumber INT = NULL,
    @StartDate DATE = NULL,
    @EndDate DATE = NULL
)
AS
BEGIN
SET NOCOUNT ON;

    SELECT 
        T1.EMPLOYEE         AS [Empolyee Number],
        T2.LAST_NAME        AS [Last Name],
        T2.FIRST_NAME       AS [First Name],
        T1.DST_ACCT_UNIT    AS [Distribution Account Unit],
        T3.DESCRIPTION,
        SUM(T1.WAGE_AMOUNT) AS [Wage Amount]    
    FROM 
        JOBCODE T3, 
        EMPLOYEE T2 LEFT OUTER JOIN 
        PRTIME T1 ON 
            T2.COMPANY = T1.COMPANY and 
            T2.EMPLOYEE = T1.EMPLOYEE
    WHERE 
        T1.DIST_COMPANY = @GLNumber and 
        CONVERT(DATE, TR_DATE, 101) BETWEEN @StartDate AND @EndDate AND
        T1.PAY_SUM_GRP in ('TPC', 'TDS') and 
        T2.JOB_CODE = T3.JOB_CODE and 
        T2.COMPANY = T3.COMPANY
    GROUP BY
        T1.EMPLOYEE,
        T2.LAST_NAME,
        T2.FIRST_NAME,
        T1.DST_ACCT_UNIT,
        T3.DESCRIPTION
END

我相信你可以看到,两个查询之间的最大区别是第一个运行已声明的变量,而第二个使用输入参数。

两个查询都返回相同,正确的结果。但是,在我的系统上运行静态查询所需的时间不到1秒,而从我的系统执行存储过程需要花费3 1/2分钟。

我不明白为什么静态查询和存储过程之间的执行时间之间存在这样的差异(我希望执行时间相似,特别是在这样一个简单的查询上)。

我可能遇到这种效率差异的潜在原因是什么?

据我所知,存储过程通常不会提供针对静态查询的性能优势,但是,与静态查询相比,我从未体验过存储过程执行效果不佳。

有没有办法纠正这个性能问题?我在SQL Server 2008 R2,SP1上运行。

澄清 运行存储过程时,我传入的参数与静态查询中使用的参数相同。

2 个答案:

答案 0 :(得分:0)

在静态版本中,StartDate和EndDate的变量已分配值。

在SP版本中,它们是NULL。

SP版本必须在整个日期范围内运行,而静态版本可以在相关日期范围内运行(可能使用索引)。

答案 1 :(得分:0)

好的,我可以通过更新查询中的FROMWHERE子句来解决这个问题。基本上,由于某种原因,存储过程不喜欢使用逗号代替INNER JOIN ... ON。这使存储过程的执行时间缩短到不到一秒。

最终程序如下:

ALTER PROCEDURE [dbo].[rptTipReport_ByCompany]
(
    @GLNumber INT = NULL,
    @StartDate DATE = NULL,
    @EndDate DATE = NULL
) 
AS
BEGIN
SET NOCOUNT ON;
    SELECT 
        T1.EMPLOYEE         AS [Empolyee Number],
        T2.LAST_NAME        AS [Last Name],
        T2.FIRST_NAME       AS [First Name],
        T1.DST_ACCT_UNIT    AS [Distribution Account Unit],
        T3.DESCRIPTION,
        SUM(T1.WAGE_AMOUNT) AS [Wage Amount]    
    FROM 
        PROD90.dbo.PRTIME T1 
        LEFT JOIN PROD90.dbo.EMPLOYEE T2 on T1.EMPLOYEE = T2.EMPLOYEE
        INNER JOIN PROD90.dbo.JOBCODE T3 on T2.JOB_CODE = T3.JOB_CODE

    WHERE 
        T1.DIST_COMPANY = @GLNumber and 
        CONVERT(DATE, TR_DATE, 101) BETWEEN @StartDate AND @EndDate AND
        T1.PAY_SUM_GRP in ('TPC', 'TDS') 
    GROUP BY
        T1.EMPLOYEE,
        T2.LAST_NAME,
        T2.FIRST_NAME,
        T1.DST_ACCT_UNIT,
        T3.DESCRIPTION
END