我得到一些奇怪的东西。我跑了这个sql:
SELECT Id , GameTypeId , PlayerId , BetAmount , Profit ,
DateAndTime
FROM Results
WHERE DateAndTime >= DATEADD (DAY , -1 , SYSDATETIME ())
AND
DateAndTime < SYSDATETIME ()
ORDER BY DateAndTime ASC;
我在日期栏上有非群集索引
并且返回的实际行数为
表中的1600016行中有672行。
(估计的行是1)
之后我运行了这个sql:
declare @d DATETIME2(7)
set @d = DATEADD (DAY , -1 , SYSDATETIME ())
declare @d2 DATETIME2(7)
set @d2 = SYSDATETIME ()
SELECT Id , GameTypeId , PlayerId , BetAmount , Profit ,
DateAndTime
FROM Results
WHERE DateAndTime >= @d
AND
DateAndTime < @d2
ORDER BY DateAndTime ASC;
并且实际执行计划是TABLE SCANE !!!
并且返回的实际行数为
表中的1600016行中有672行。
(估计行数为144000 r0ws)
有些人知道这里发生了什么事吗?!?!?
答案 0 :(得分:4)
因为您正在为值使用变量,所以查询优化器不知道WHERE子句的选择性,并决定使用表扫描。 尝试在DateAndTime字段上创建聚簇索引。
答案 1 :(得分:2)
尝试
declare @d DATETIME2(7)
set @d = DATEADD (DAY , -1 , SYSDATETIME ())
declare @d2 DATETIME2(7)
set @d2 = SYSDATETIME ()
SELECT Id , GameTypeId , PlayerId , BetAmount , Profit ,
DateAndTime
FROM Results
WHERE DateAndTime >= @d
AND
DateAndTime < @d2
ORDER BY DateAndTime ASC
OPTION (RECOMPILE);
一旦知道变量的值,这将重新编译语句的计划,因此允许使用准确的基数估计。如果你知道你将总是选择一个非常小的百分比,你可以使用FORCESEEK
(如果是SQL Server 2008)提示来避免重新编译,但是使用这个提示对于较大的范围可能是灾难性的,因为它的数量很多密钥查找!
答案 2 :(得分:1)
除了马丁的回答......
根据变量, Results.DateAndTime
也应该是datetime2(7)。如果没有,您很可能有数据类型优先级问题
答案 3 :(得分:0)
如果估计的行数非常高,优化器会得出结论:全表扫描可能比索引搜索+ RID查找更有效。
所以,问题是为什么估计的行数偏离了?
不幸的是,我还没有深入SQL Server。但是,我会说这是因为绑定参数;这可能会影响基数估计(估计行数)(至少在其他数据库中)。
答案 4 :(得分:0)
我发现当估计的行数与实际数字大不相同时,您可能会在某处丢失统计信息,或者您拥有的统计信息已过期。您应该能够查看SSMS中的查询计划,并根据不同运营商的基数估算值找出哪些统计信息丢失或过期。