我有两个几乎相同的查询,第一个是带有变量的静态查询,第二个是带有输入参数的存储过程。
静态查询
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上运行。
澄清 运行存储过程时,我传入的参数与静态查询中使用的参数相同。
答案 0 :(得分:0)
在静态版本中,StartDate和EndDate的变量已分配值。
在SP版本中,它们是NULL。
SP版本必须在整个日期范围内运行,而静态版本可以在相关日期范围内运行(可能使用索引)。
答案 1 :(得分:0)
好的,我可以通过更新查询中的FROM
和WHERE
子句来解决这个问题。基本上,由于某种原因,存储过程不喜欢使用逗号代替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