使用变量查询优化
Query optimization with variables
首先,如果这个问题很常见,我深表歉意...我似乎找不到要搜索的正确术语...
我有一个有点大的 table,它有一个增量 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 服务器执行这些优化,并且
- 我该如何解决?
您因使用局部变量而受到隐式 OPTION (OPTIMIZE FOR UNKNOWN)
的困扰。有关详细信息,请参阅 this link。优化器无法通过参数嗅探局部变量,而是使用基于平均值的总体计划。使用常量时,它能够使用更好的统计数据并通过使用搜索进行优化。
要解决此问题,您可能需要创建一个存储过程并提供参数而不是变量。您可能还需要添加 OPTION (RECOMPILE)
提示以获得与使用常量时类似的优化。否则,您将受制于在第一次执行期间嗅探到的任何参数。
首先,如果这个问题很常见,我深表歉意...我似乎找不到要搜索的正确术语...
我有一个有点大的 table,它有一个增量 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 服务器执行这些优化,并且
- 我该如何解决?
您因使用局部变量而受到隐式 OPTION (OPTIMIZE FOR UNKNOWN)
的困扰。有关详细信息,请参阅 this link。优化器无法通过参数嗅探局部变量,而是使用基于平均值的总体计划。使用常量时,它能够使用更好的统计数据并通过使用搜索进行优化。
要解决此问题,您可能需要创建一个存储过程并提供参数而不是变量。您可能还需要添加 OPTION (RECOMPILE)
提示以获得与使用常量时类似的优化。否则,您将受制于在第一次执行期间嗅探到的任何参数。