SQL Server 2012存储过程运行缓慢

kud*_*lur 1 sql sql-server sql-server-2012

我有一个SQL Server存储过程,它在SQL Server 2008 R2上运行良好.

当我尝试在SQL Server 2012上运行它时,运行需要很长时间.

但是,如果我在存储过程中创建局部变量并将输入参数的值复制到那些局部变量中并使用它们而不是输入参数,则查询运行并返回比SQL Server 2008 R2数据库更快的结果(请注意2008 R2和2012服务器在同一个盒子上运行).

你能否详细介绍一下这里发生了什么?

Luk*_*zda 7

通过创建局部变量和重新绑定值,可以禁用参数嗅探:

参数嗅探是SQL Server通过使用第一次执行存储过程时传递的调用参数为存储过程创建最佳计划的过程

对具有相同参数的相同存储过程的每次后续调用也将获得最佳计划,而具有不同参数值的调用可能并不总是获得最佳计划

运行速度慢:

CREATE PROC [dbo].[DisplayBillingInfo]
  @BeginDate DATETIME,
  @EndDate DATETIME
AS
BEGIN
  SELECT BillingDate, BillingAmt
  FROM BillingInfo
  WHERE BillingDate between @StartDate AND @StopDate; 
END
Run Code Online (Sandbox Code Playgroud)

快速运行(因为它必须每次都计算新的执行计划):

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
Run Code Online (Sandbox Code Playgroud)

案例是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
Run Code Online (Sandbox Code Playgroud)

使用查询提示:

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
Run Code Online (Sandbox Code Playgroud)