我有一张大约有2亿行的表格。该表包含许多列,但目前只有主键和非聚集索引基于索引的datetime列。
第一个查询将在不到一秒的时间内返回零行。
SELECT *
FROM GenericTable
WHERE GenericDate > '01-01-1753' AND GenericDate <= '01-29-1753'
此查询需要花费相当长的时间才能返回零行,大约两分钟。
DECLARE @startDate DATETIME, @endDate DATETIME
SET @startDate = '01-01-1753'
SET @endDate = '01-29-1753'
SELECT *
FROM GenericTable
WHERE GenericDate > @startDate AND GenericDate <= @endDate
使用包含数据的日期范围,性能会好一点吗?第一个查询将在不到一秒的时间内返回1000行,第二个查询仍需要30秒或更长时间才能返回相同的数据。
编辑:我还告诉我执行计划,第二个查询没有使用索引?第一次查询:
Select <- Nested Loops (Inner Join) - 0% <- Index Seek (NonClustered) - 0%
<- Key Lookup (Clustered) - 100%
第二次质疑:
Select <- Parallelism (Gather Streams) - 10% <- Clustered Index Scan (Clustered) - 90%
答案 0 :(得分:5)
执行计划缓存和参数是一个众所周知的问题 嗅探。
前段时间我写了关于参数嗅探,SQL的情况 编译和缓存适合于a的执行计划 参数的某个值,但对其他值不是最佳的。 参数嗅探的另一面是 - 当优化器时 根本无法闻到。
当批次提交给优化器时,任何值都是 参数(来自存储过程,自动参数化或 sp_executesql)为优化器所知。任何价值也是如此 SQL语句中使用的常量。局部变量的值, 但是,不是。
当where子句中使用的变量值未知时,优化器不知道使用什么值来估计数字 受影响的行。因此,它不知道表中有多少行 将满足条件。