我有一个很长的复杂查询,我已经分解为TVF,以便于维护和创建其他报告所基于的基础数据。但是,当我参数化输入时,执行查询需要更长的时间; top查询在~3秒内执行,第二个查询在40秒内执行。
我认为这可能是由于参数嗅探,虽然这些是内联TVF,所以我不确定它是多么相关。我尝试用存储过程包装进行测试并明确地将参数声明为DATETIME
,但我似乎无法到达任何地方。
DECLARE @Month int = 4
DECLARE @year int = 2015
DECLARE @startDate DateTime, @endDate DateTime
SELECT @startDate = Dateadd(mm, ( @year - 1900 ) * 12 + @month - 1, 0 )
SELECT @endDate = DATEADD(DAY, -1, Dateadd(mm, ( @year - 1900 ) * 12 + @month, 0 ))
/* Constants */
SELECT
*,
DATEADD(MINUTE, ((CONVERT(DECIMAL, Mileage) / [Days]) / 56) * 60, '1900-01-01') EstDrivingTimeDay,
DATEADD(MINUTE, duration / [days], '1900-01-01') EstTimeOnSiteDay,
DATEADD(MINUTE, ((CONVERT(DECIMAL, Mileage) / [Days]) / 56) * 60, '1900-01-01') + DATEADD(MINUTE, duration / [days], '1900-01-01') TotalWorkingTime
FROM
GetDriverCreditsByMonthYearBaseViewTrips('2015-04-01', '2015-04-30' )
/* Stored Proc Wrapper */
EXEC DriverTripsByMonthYear @month, @year
/* Params in SQL */
SELECT
*,
DATEADD(MINUTE, ((CONVERT(DECIMAL, Mileage) / [Days]) / 56) * 60, '1900-01-01') EstDrivingTimeDay,
DATEADD(MINUTE, duration / [days], '1900-01-01') EstTimeOnSiteDay,
DATEADD(MINUTE, ((CONVERT(DECIMAL, Mileage) / [Days]) / 56) * 60, '1900-01-01') + DATEADD(MINUTE, duration / [days], '1900-01-01') TotalWorkingTime
FROM
GetDriverCreditsByMonthYearBaseViewTrips(@startDate, @endDate ) option (optimize for (@startDate unknown, @endDate unknown))
sproc DriverTripsByMonthYear
CREATE PROCEDURE DriverTripsByMonthYear
-- Add the parameters for the stored procedure here
@month INT,
@year INT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @startDate DATETIME
DECLARE @endDate DATETIME
SELECT @startDate = Dateadd(mm, ( @year - 1900 ) * 12 + @month - 1, 0 )
SELECT @endDate = DATEADD(DAY, -1, Dateadd(mm, ( @year - 1900 ) * 12 + @month, 0 ))
-- Insert statements for procedure here
SELECT
*,
DATEADD(MINUTE, ((CONVERT(DECIMAL, Mileage) / [Days]) / 56) * 60, '1900-01-01') EstDrivingTimeDay,
DATEADD(MINUTE, duration / [days], '1900-01-01') EstTimeOnSiteDay,
DATEADD(MINUTE, ((CONVERT(DECIMAL, Mileage) / [Days]) / 56) * 60, '1900-01-01') + DATEADD(MINUTE, duration / [days], '1900-01-01') TotalWorkingTime
FROM
GetDriverCreditsByMonthYearBaseViewTrips(@startDate, @endDate ) option (optimize for (@startDate unknown, @endDate unknown))
END
GO
总之,我需要将月份和年份转换为DateTime,并将其作为参数传递给内联TVF,而不需要花费10倍的执行时间。
N.B 两个查询都生成相同的执行计划
答案 0 :(得分:1)
我要做的第一件事就是检查你是否成为parameter sniffing的受害者。如果确实如此,修复它的方法之一就是使用
option (optimize for (@startDate unknown, @endDate unknown))
在您的TVF正文中