为什么主键上的集群键查找每次执行的估计行数很高?

Ril*_*jor 10 sql-server execution-plan azure-sql-database query-performance

我们有一个带有 Key Lookup 的查询,它估计每次执行有数千行。据我了解,每次执行应该只有一行。我知道统计数据可能会产生误导,但优化器不明白主键是唯一的吗?

此查询中涉及的表具有以下形式的聚集主键:

/****** Object:  Index [PK_Table_Name]    Script Date: 6/16/2021 9:52:12 AM ******/
ALTER TABLE [dbo].[Table_Name] ADD  CONSTRAINT [PK_Table_Name] PRIMARY KEY CLUSTERED 
(
    [Table_Name_ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)

据我了解,主键提供了对表中单行的唯一引用。

因此,对于它在非聚集索引中找到的每一行,它应该能够使用该索引对聚集索引的引用来检索它所需的单行,以满足其正在处理的行的其余查询过滤。(这是一个嵌套循环连接运算符。)

那么为什么它估计将近 4000 行将作为 Key Lookup 的一部分返回?(不是“对于所有执行”,大约 36,000,000 是 4000 和它期望从非聚集索引查找中得到的 9000 行的乘积。)

查询计划显示每次执行的大行以进行键查找

运行时统计数据显示该聚集索引查找有 2851 行和 2851 次执行,这正是我所期望的。

运行时统计信息显示聚集索引搜索每次执行一行

如果有帮助,这是在 Azure SQL 数据库中,带有@@version

Microsoft SQL Azure (RTM) - 12.0.2000.8 
    Apr 29 2021 13:52:20 
    Copyright (C) 2019 Microsoft Corporation
Run Code Online (Sandbox Code Playgroud)

Jos*_*ell 10

查看 Paul White 的博客文章Cardinality Estimation Bug with Lookups以获得问题的答案:

在 SSMS 执行计划中,应用过滤谓词的键或 RID 查找的估计行数可能是错误的。

这个错误不会影响优化器的最终计划选择,但看起来确实很奇怪。

博文接着说,计划在 2020 年 8 月进行修复,以在新的 160 兼容级别下解决此问题:

计划在 SQL Server 2019(兼容级别 160)之后的版本中对此进行修复

  • 它显然比从外面看起来更复杂。在某些方面,看到问题得到解决我会感到难过。现在有点像老朋友了…… (3认同)