我有一个存储过程接受日期输入,如果没有传入值,则该日期输入稍后设置为当前日期:
CREATE PROCEDURE MyProc
@MyDate DATETIME = NULL
AS
IF @MyDate IS NULL SET @MyDate = CURRENT_TIMESTAMP
-- Do Something using @MyDate
我遇到的问题是,如果@MyDate
在第一次编译存储过程时作为NULL
传入,则所有输入值(NULL
或其他)的性能总是很糟糕,如果在编译存储过程时传入日期/当前日期,则对于所有输入值(NULL
或其他),性能都可以。
令人困惑的是,即使使用@MyDate的值实际 NULL
(并且未设置为CURRENT_TIMESTAMP
,生成的糟糕执行计划也很糟糕通过IF声明)
我发现禁用参数嗅探(通过欺骗参数)解决了我的问题:
CREATE PROCEDURE MyProc
@MyDate DATETIME = NULL
AS
DECLARE @MyDate_Copy DATETIME
SET @MyDate_Copy = @MyDate
IF @MyDate_Copy IS NULL SET @MyDate_Copy = CURRENT_TIMESTAMP
-- Do Something using @MyDate_Copy
我知道这与参数嗅探有关,但我所见的“参数嗅探变坏”的所有示例都涉及使用传递的非代表性参数编译存储过程,但是在这里我我发现执行计划对SQL服务器可能认为参数可能在执行语句时可能采用的所有可能值都很糟糕 - NULL
,CURRENT_TIMESTAMP
或其他。
有没有人知道为什么会这样?
答案 0 :(得分:7)
基本上是 - 参数嗅探(在某些补丁级别中)SQL Server 2005严重受损。我已经看到计划实际上永远不会完成(在小数据集上几小时内),即使是小的(几千行)数据集,一旦参数被屏蔽,这些数据集在几秒钟内完成。这是在参数始终为相同数字的情况下。我想补充一点,在我处理这个问题的同时,我发现LEFT JOIN / NULL没有完成时会遇到很多问题,我用NOT IN或NOT EXISTS替换它们,这就把计划解决了。同样,(非常糟糕的)执行计划问题。在我处理这个问题的时候,DBA不会给我SHOWPLAN访问权限,并且因为我开始屏蔽每个SP参数,所以我没有任何进一步的执行计划问题,我将不得不深入研究这个问题。
在SQL Server 2008中,您可以使用OPTIMIZE FOR UNKNOWN
。
答案 1 :(得分:1)
我能够在(SQL Server 2005)中解决此问题而不是通过重新声明本地参数来屏蔽参数的一种方法是添加查询优化器提示。
这是一篇很好的博客文章,详细介绍了它: Parameter Sniffing in SqlServer 2005
我用过:OPTION(针对(@p =' - 1')优化)
答案 2 :(得分:0)
在过程内部声明过程参数,并将外部参数传递给内部..编译..