我有一个包含大约 2 亿行的表。该表包含许多列,但目前只有主键和一个基于日期时间列的非聚集索引。
第一个查询将在不到一秒内返回零行。
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%
最佳答案
这是一个众所周知的执行计划缓存和参数问题 嗅探。
A while back I wrote about parameter sniffing, the situation where SQL compiles and caches an execution plan that is appropriate for a certain value of a parameter, but is non optimal for other values. There’s another side to parameter sniffing though – when the optimiser can’t sniff at all.
When a batch is submitted to the optimiser, the value of any parameters (from stored procedure, auto parametrisation or sp_executesql) are known to the optimiser. So are the value of any constants used in the SQL statement. The value of local variables, however, are not.
When the value of a variable used in the where clause is not known, the optimiser has no idea what value to use to estimate the number of affected rows. Hence, it has no idea how many rows from the table will satisfy the condition.
关于sql - 使用变量时的查询性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38361164/