为什么 WHERE 子句中的硬编码日期比相同日期作为参数提供更快的性能?

Why hard-coded dates in WHERE clause gives faster performance then same dates as a parameters?

如果我将日期放在 WHERE 子句中(第一个查询)或者如果我将相同的日期作为参数(第二个查询),为什么性能会有如此巨大的差异

--------/* Execution time 3 sec*/ 
   select 
            tblNoteDiaries.DueDate,
            col2,
            col3
    from MyTable 
    where CAST(tblNoteDiaries.DueDate as date) <= cast(getdate()as date) and cast( tblNoteDiaries.DueDate as date) >= CAST('2017-09-29' as DATE)

--------/* Execution time 10 sec*/    
    declare     @DateFrom datetime = '2017-09-29',
                @DateTo datetime = '2017-10-05'
    select 
            tblNoteDiaries.DueDate,
            col2,
            col3
    from    MyTable 
    where   CAST(tblNoteDiaries.DueDate as date)  >= @DateFrom   and cast( tblNoteDiaries.DueDate as date) <= @DateTo 

我需要将此查询作为存储过程,在不降低性能的情况下使用日期参数的最佳方法是什么?

因为你的变量声明为datetime。这具有更高的数据类型优先级。因此,您要将 DueDate 列显式转换为 date,然后再次转换为 datetime

对您的变量使用 date,您应该会看到相同的性能。更好的是,如果类型已经正确,请不要 CAST 您的日期列。

我使用以下查询在我的数据库上进行了模拟

select sum(PrinBal)
from fpc
where SnapshotDt >= '2017-06-01' and SnapshotDt <= '2017-06-30'
go

declare @sd date = '2017-06-01'
declare @ed date = '2017-06-30'
select sum(PrinBal)
from fpc
where SnapshotDt >= @sd and SnapshotDt <= @ed
go

并检查了执行计划。第一个查询为 48%,第二个查询为 52%。

然后我将 option(recompile) 添加到第二个查询中,然后两者都采用了完全相同的百分比

declare @sd date = '2017-06-01'
declare @ed date = '2017-06-30'
select sum(PrinBal)
from fpc
where SnapshotDt >= @sd and SnapshotDt <= @ed
option(recompile)
go

正如尼克所说,是参数嗅探

您可以使用更新的统计信息或对您的查询和存储过程使用 RECOMPILE 选项来摆脱参数嗅探。