执行计划-读取比表中更多的记录

OED*_*Dev 4 sql-server execution-plan

这里是 SQL 新手,所以很抱歉,如果这是非常基本的东西。

SQL 服务器 2019、Windows

2 个表 - FixingHeader 和 Product

简单查询读取所有固定标头并查找相关产品

 select [f].[Id], [f].[FixingHeaderReference], [p].[Description] from [dbo].[FixingHeader] as f 
       JOIN [Product] AS [p] ON [f].[ProductId] = [p].[Id]
Run Code Online (Sandbox Code Playgroud)

我的 FixingHeader 数据库中只有 7 条记录

看着执行计划,对一些结果感到惊讶。

1 - 为什么计划显示的读取记录多于表本身?

执行计划

认为这与 3 次处决有关,但为什么是 3 次呢?

3 次处决

2 - 为什么 Product 表使用聚集索引扫描而不是 Seek?正在使用具有索引的主键 ID 读取产品

谢谢!

J.D*_*.D. 5

为什么计划显示的读取记录多于表本身?

就像斯兰达提到的那样,这是因为Nested Loops Join用于将数据连接在一起的运算符。使用时Nested Loops,它会迭代要连接的整个数据集合(本例中为 7 行),以获取要连接的外部数据集合中的行数(3 行)。这就是 21 的由来,7 x 3。

Nested Loops通常是在将小型数据集连接在一起时选择的连接运算符(或者至少当一个数据集很小并且另一个数据集在连接谓词上建立索引时)。替代选项Hash Join和 的Merge Join开销对于小型数据集通常会较慢。

为什么 Product 表使用聚集索引扫描而不是查找?

因为您的查询似乎要求表中的每一行Product(没有显式过滤,例如子句WHERE),所以您遇到了所谓的临界点,即 SQL Server 引擎认为扫描索引比查找索引更有效。当您询问表中的每一行时,这样做是正确的。

临界点基于几个因素,包括查询将从索引返回的行数与索引实际存储的总行数。由于表/索引中的行数如此之少,可能很容易达到临界点,除非您一次只查询一行Product。但同样,由于您对 all 感兴趣Products,因此在这种情况下引擎选择的查询计划可能是最快的(与索引查找相反)。