怎么会发生SP sql server

时间:2011-01-13 11:33:07

标签: sql-server database tsql stored-procedures

我得到一些奇怪的东西。我跑了这个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)

有些人知道这里发生了什么事吗?!?!?

5 个答案:

答案 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中的查询计划,并根据不同运营商的基数估算值找出哪些统计信息丢失或过期。