使用变量时的查询性能

Der*_*ler 3 sql sql-server

我有一张大约有2亿行的表.该表包含许多列,但目前只有主键和非聚簇索引基于索引的datetime列.

第一个查询将在不到一秒的时间内返回零行.

SELECT *
FROM GenericTable
WHERE GenericDate > '01-01-1753' AND GenericDate <= '01-29-1753'
Run Code Online (Sandbox Code Playgroud)

此查询需要过长的时间才能返回零行,大约两分钟.

DECLARE @startDate DATETIME, @endDate DATETIME

SET @startDate = '01-01-1753'
SET @endDate = '01-29-1753'

SELECT *
FROM GenericTable
WHERE GenericDate > @startDate AND GenericDate <= @endDate
Run Code Online (Sandbox Code Playgroud)

使用包含数据的日期范围,性能会好一点吗?第一个查询将在不到一秒的时间内返回1000行,第二个查询仍需要30秒或更长时间才能返回相同的数据.

编辑:我也告诉我执行计划,第二个查询不使用索引?

第一次查询:

Select <- Nested Loops (Inner Join) - 0% <- Index Seek (NonClustered) - 0%
                                         <- Key Lookup (Clustered) - 100%
Run Code Online (Sandbox Code Playgroud)

第二次查询:

Select <- Parallelism (Gather Streams) - 10% <- Clustered Index Scan (Clustered) - 90%
Run Code Online (Sandbox Code Playgroud)

Has*_*san 5

这是执行计划缓存和参数嗅探的一个众所周知的问题.

引用本文

前段时间我写了一篇关于参数嗅探的文章,其中SQL编译并缓存了一个适合某个参数值的执行计划,但对其他值不是最佳的.参数嗅探的另一面是 - 当优化器根本无法嗅探时.

将批处理提交给优化程序时,优化程序将知道任何参数的值(来自存储过程,自动参数化或sp_executesql).SQL语句中使用的任何常量的值也是如此.但是,局部变量的值不是.

当where子句中使用的变量的值未知时,优化器不知道使用什么值来估计受影响的行数.因此,它不知道表中有多少行会满足条件.

  • 并且添加"OPTION(RECOMPILE)"将允许值被嗅探. (2认同)