2009-06-17 75 views
9

我都接受,如果没有值传入稍后设置为当前日期的日期输入存储过程:SQL可怜的存储过程的执行计划性能 - 参数嗅探

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(而不是由IF语句设置为CURRENT_TIMESTAMP

我VE发现禁用参数嗅探(通过欺骗参数)解决我的问题:

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服务器可能认为该参数在执行语句时可能采取的所有可以想到的值都很糟糕 - NULLCURRENT_TIMESTAMP或其他。

有没有人对这种情况发生的原因有所了解?

+1

这是有趣的,但你并不是在这里的任何地方提问... – cjk 2009-06-17 14:38:49

回答

6

基本上是 - 参数嗅探(在某些补丁级别中)SQL Server 2005被严重破坏。我发现即使对于小数据行(几千行),一旦参数被屏蔽后,完成的计划也不会完成(在小数据集内几小时内)即可完成。这是在参数总是相同的情况下。我会补充一点,在我处理这个问题的同时,我发现LEFT JOIN/NULL没有完成的问题很多,我用NOT IN或NOT EXISTS取代了它们,并且这个解决方案完成了一些任务。再次,(很差)的执行计划问题。当时我正在处理这个问题,DBA不会给我SHOWPLAN访问权限,而且由于我开始屏蔽每个SP参数,因此我没有任何进一步的执行计划问题,因为我不得不深入研究这些问题。

在SQL Server 2008中,您可以使用OPTIMIZE FOR UNKNOWN

0

在(SQL Server 2005)中解决此问题的一种方法,而不是仅通过重新声明本地参数来掩盖参数,而是添加查询优化器提示。

这里是一个很好的博客贴子,更多地谈论它: Parameter Sniffing in SqlServer 2005

我用:OPTION(优化(@p = '-1'))