为什么聚集索引搜索会返回比基础表中的行数更高的“实际行数”?

Tod*_*ier 8 sql-server optimization execution-plan azure-sql-database

我正在解决与 SQL Server(技术上是 Azure SQL 数据库)相关的问题,偶尔会选择错误的执行计划,大概是由于统计数据不准确。sp_updatestats每次都修复它,直到几个小时或几天后,一个糟糕的计划再次被缓存。

看着“糟糕”的计划,我注意到一些让我感到奇怪的事情:在当前大约有 170 万行的表上有一个聚集索引查找。此操作的“估计行数”约为 1200,这绝对符合我在这种情况下对该操作所期望的平均行数,但“实际行数”超过 6000 万!沿着这个叶节点的粗线,在所有 6000 万个节点上执行各种下游操作,例如连接和排序,导致过慢、溢出到 tempdb 和其他坏处。

我一定误解了聚集索引查找实际上是做什么的,因为我认为它不可能“输出”比基础表中更多的行。什么可能导致这种情况?更好的是,有关如何修复它的任何指示?

[包含诸如“sp_updatestats每次修复它但无法弄清楚如何永久修复它?阅读这篇文章”之类的奖励积分。这是我们最近在几个不同方面的普遍问题。]

For*_*est 8

Seek 返回更多行,因为它位于嵌套循环的内部(底部)侧。外部操作返回的每一行都会导致一个新的 Seek 操作。因此,您不是从单个 Seek 中获得 60m 行,而是从其中的 9000 多个(执行次数)中获得。

另请注意:在查看估计时,估计的总行数将为估计执行次数乘以估计行数