【发布时间】:2016-01-06 12:10:38
【问题描述】:
首先,如果这个问题是常见问题,我深表歉意……我似乎无法找到正确的搜索字词……
我有一个有点大的表,它有一个递增的 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。但是,第二个查询改为对主键(即 ID)执行 2 scans。
所以,我的问题有两个:
- 为什么 SQL Server 会执行这些优化,以及
- 我该如何解决?
【问题讨论】:
-
Parameters 生成的独立查询完全不同,SQL Server 可以使用常量而不是变量进行更准确的估计,从而得出更好的计划。您可以尝试使用 Plan Guides 强制使用不同的计划
-
简单的一点是,根据数据范围查询优化器必须在索引搜索和索引扫描之间进行选择。
-
@lad2025,虽然我不认为参数链接与我的场景有任何关系(这不是存储过程),但听起来
option(recompile)应该在 MSSQL 2008 和更新...这至少意味着有一个合理的解决方案向前发展... -
这不是存储过程。局部变量具有与上面链接中描述的相同的行为。想一想,当你在你的案例中传递一个常量时,一天范围查询优化器知道它很窄并使用索引搜索。当您传递变量时,它会尝试制定通用执行计划。
-
看到this和你的问题完全一样
标签: tsql sql-server-2005