SQL差的存储过程执行计划性能 - 参数嗅探

Jus*_*tin 10 sql t-sql sql-server parameter-sniffing sql-execution-plan

我有一个存储过程接受一个日期输入,如果没有传入值,则该日期输入稍后设置为当前日期:

CREATE PROCEDURE MyProc
    @MyDate DATETIME = NULL
AS
    IF @MyDate IS NULL SET @MyDate = CURRENT_TIMESTAMP
    -- Do Something using @MyDate
Run Code Online (Sandbox Code Playgroud)

我遇到问题,如果@MyDateNULL第一次编译存储过程时传入if ,则对于所有输入值(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
Run Code Online (Sandbox Code Playgroud)

我知道这与参数嗅探有关,但我看到的所有"参数嗅探变坏"的例子都涉及使用传递的非代表性参数编译存储过程,但是在这里我看到了执行计划是可怕的SQL Server可能认为执行该语句其中参数可能需要在该点所有可能的值- NULL,CURRENT_TIMESTAMP或以其他方式.

有没有人知道为什么会这样?

Cad*_*oux 7

基本上是 - 参数嗅探(在一些补丁级别)SQL Server 2005严重破坏.我已经看到计划实际上永远不会完成(在小数据集上几小时内),即使是小的(几千行)数据集,一旦参数被屏蔽,这些数据集在几秒钟内完成.这是在参数始终为相同数字的情况下.我想补充一点,在我处理这个问题的同时,我发现LEFT JOIN/NULL没有完成时会遇到很多问题,我用NOT IN或NOT EXISTS替换它们,这就把计划解决了.同样,(非常糟糕的)执行计划问题.在我处理这个问题时,DBA不会给我SHOWPLAN访问权限,因为我开始屏蔽每个SP参数,所以我没有任何进一步的执行计划问题,我将不得不深入研究这个问题. .

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