【问题标题】:How can a table scan return more rows than are in the table?表扫描如何返回比表中更多的行?
【发布时间】:2011-05-26 19:41:31
【问题描述】:

我对一个包含错误统计信息和碎片索引的数据库进行了复杂查询。我感到困惑的是,当我检查一个实际的查询计划时,我从一个有 23 K 行的表上的表扫描中得到了 54 M 行。在查询计划的更进一步,该表与自身连接(23 K 中只有 260 K 行)。这怎么可能?

运行一些其他查询或重建索引和统计信息会使这种情况消失,我只是想了解为什么会发生这种情况。

我在还原同一数据库时使用 SQL 2005 和 SQL 2008 R2 重现了这一点。

更新:是的,这是一个实际的计划。行数是 20039(不是上面提到的 23 K)。这是最右边的节点之一。

【问题讨论】:

  • 嗯...表格被扫描多次了吗?
  • 该表在查询中是自联接的,这是有充分理由的。在查询计划中,它被扫描两次(上面提到的表扫描)并且在表上进行了三次索引搜索。
  • 这是预估的执行计划,还是实际的执行计划?
  • 是的 - 实际计划,附上图片。
  • @Pavel - 有趣的是 2701 * 20039 给出了完全正确的数字。确定它没有被执行 2701 次?它是在连接的内侧还是什么的?

标签: sql-server sql-execution-plan


【解决方案1】:

看起来执行计划中的这个节点是嵌套循环连接中涉及的“第二个”表,“第一个”表中有 2701 行(感谢 Martin!)。

由于 HistoricalPrice 表上似乎没有适当的索引,因此必须为循环连接中的每一行扫描堆,结果总共有 2701*20039 = 54,125,339 行。来自嵌套循环运算符的行数将是连接/匹配行的总数。

虽然执行计划仅显示作为一个节点访问的表,但循环连接最终会访问该表的次数与行数一样多。如果没有索引,则必须扫描整个表,每次将 20,039 行返回给嵌套循环运算符。

如果在表上放置了一个适当的索引来支持连接,那么可能只会寻找一行,因此将更少的行发送回嵌套循环。

【讨论】:

  • 是的,在树的更上方有一个嵌套循环,另一端请求 2701 行。
猜你喜欢
  • 1970-01-01
  • 2020-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多