我有一个SQL Server存储过程,它在SQL Server 2008 R2上运行良好。
当我尝试在SQL Server 2012上运行它时,运行需要很长时间。
但是如果我在存储过程中创建局部变量并将输入参数的值复制到那些局部变量中并使用它们而不是输入参数,查询运行并返回结果比SQL Server 2008 R2数据库更快(请注意2008年R2和2012服务器在同一个盒子上运行。)
请您详细了解这里发生的事情?
答案 0 :(得分:7)
通过创建局部变量并重新绑定值,您可以停用 parameter sniffing :
参数嗅探是SQL Server创建的过程 使用调用参数的存储过程的最佳计划 在第一次执行存储过程时传递
对具有相同参数的相同商店流程的每次后续调用也将获得最佳计划,而具有不同参数值的调用可能无法始终获得最佳计划
慢跑:
CREATE PROC [dbo].[DisplayBillingInfo]
@BeginDate DATETIME,
@EndDate DATETIME
AS
BEGIN
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between @StartDate AND @StopDate;
END
快跑(因为每次必须计算新的执行计划):
CREATE PROC [dbo].[DisplayBillingInfo]
@BeginDate DATETIME,
@EndDate DATETIME
AS
BEGIN
DECLARE @StartDate DATETIME = @BeginDate;
DECLARE @StopDate DATETIME = @EndDate;
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between @StartDate AND @StopDate;
END
案例是SQL Server优化器无法重用缓存计划并每次评估它。
这与您使用WITH RECOMPILE
相同:
CREATE PROC [dbo].[DisplayBillingInfo]
@BeginDate DATETIME,
@EndDate DATETIME
WITH RECOMPILE
AS
BEGIN
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between @StartDate AND @StopDate;
END
使用查询提示:
CREATE PROC [dbo].[DisplayBillingInfo]
@BeginDate DATETIME,
@EndDate DATETIME
AS
BEGIN
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between @StartDate AND @StopDate
OPTION(RECOMPILE);
-- OPTION (OPTIMIZE FOR (@StartDate UNKNOWN, @StopDate UNKNOWN))
END