首先,如果这个问题很常见,我很抱歉...我似乎无法找到正确的搜索条件...
我有一个有点大的表,它有一个增量ID和一个插入的datetime
值。它上面有几个索引,包括ID
上的主键和插入时间和ID上的非聚集索引。因此,当我编写如下的查询时,它非常快:
select min(ID), max(ID)
from tbl
where inserted between '2015-10-07' and '2015-10-08'
但是,如果我变量where子句条件(如下所示),它会慢得多:
declare @sTime datetime, @eTime datetime
select @sTime = '2015-10-07', @eTime = '2015-10-08'
select min(ID), max(ID)
from tbl
where inserted between @sTime and @eTime
当我查看两个查询计划时,我看到了明显的问题。第一个查询在插入的时间和ID的非聚集索引上使用单个seek
。但是,第二个查询会在主键上执行2 scans
(这只是ID)。
所以,我的问题是双重的:
答案 0 :(得分:3)
您使用局部变量来使用隐式OPTION (OPTIMIZE FOR UNKNOWN)
。有关详细信息,请参阅this link。优化器无法参数嗅探局部变量,并且正在使用基于平均值的一般计划。使用常量时,它可以使用更好的统计数据并通过使用搜索进行优化。
要解决此问题,您可能需要创建存储过程并提供参数而不是变量。您可能还需要添加OPTION (RECOMPILE)
提示以获得与使用常量时类似的优化。否则,您将受到第一次执行期间嗅探的任何参数的影响。