sql server:估计的行数是关闭的

时间:2010-01-05 11:58:33

标签: sql sql-server tsql

我从SQL Server(2005)获得了一个奇怪的执行计划行为。

TableName:日志
...包含大约1000行

  • ID int
  • 名称varchar(50)

查询:

SELECT * 
  FROM (SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) as Row,
               ID, Name
          FROM Log) AS LogWithRowNumbers
 WHERE Row >= 1 
   AND Row <= 2

它估计返回的行数为9(虽然它明显为2或更少) 此外,删除“和行&lt; = 2”将使执行时间增加约* 5.(“和行&lt; = 2”和“和&lt; = 9999999999999”行为相同)

我已更新统计数据。但是,这种行为很奇怪。添加行&lt; 99999999999将使查询运行得更快?为什么?

2 个答案:

答案 0 :(得分:6)

我不是SQL Server内部工作/查询优化过程的专家,但这是我的2便士(如果你愿意的话还是美分)。

我认为这是由于在WHERE子句中使用了ROW_NUMBER()值。作为一个例子,我创建了一个样本表,填充了从ID 1到1000的1000行(ID作为主键),就像你说的那样。

如果您取出ROW_NUMBER(),并根据ID列执行查询,如下所示:

Select * FROM
(
 SELECT ID, Name
 FROM Log
)
as LogWithRowNumbers
WHERE ID>=1 and ID<=2

然后它正确显示行数为2 - 正如预期的那样。

现在,向后工作,将ROW_NUMBER添加到内部SELECT,但保留WHERE子句,如下所示:

Select * FROM
(
 SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) AS RowNo,
 ID, Name
 FROM Log
)
as LogWithRowNumbers
WHERE ID>=1 AND ID <=2

这仍然显示正确的行数为2。

最后,将WHERE子句重新设置为使用RowNo作为要过滤的列而不是ID,这是估计行数跳到9时。

因此,我认为它是使用ROW_NUMBER()函数,在作为原因的WHERE子句中进行过滤。所以我想这是因为实际表列上有明显更好/更准确的统计数据,而不是这个函数产生的值。

我希望这至少提供了一个很好的起点,希望有用!

答案 1 :(得分:2)

AdaTheDev是对的。您看到此行为的原因是因为SQL Server必须先计算表的行号才能在where子句中使用它们。

这应该是获得相同结果的更有效方式:

 SELECT TOP(2) ROW_NUMBER() OVER (ORDER BY ID DESC) as Row,
 ID, Name
 FROM Log
 ORDER BY ID DESC