首页 > 解决方案 > 为什么当我加入另一个表时逻辑读取会增加

问题描述

我一直在查看我们数据库中一些长时间运行的查询,目的是减少花费的时间。我正在查看的一件事是每个表、每个查询的逻辑读取次数,但我不确定为什么某些表的逻辑读取如此之高。

我可以展示一个非常基本的示例来重现“问题”,而不是发布长查询。我创建了这个查询:

SELECT p.Id
FROM 
    Products p
    INNER JOIN StaffMembers sm ON p.CreatedById = sm.Id AND sm.IsDeleted = 0
WHERE p.DateCreated > '01-MAY-2021'

StaffMembers表的逻辑读取数为 6,返回的行数为 219

执行计划

如果我稍微更改查询,以引入另一个表:

SELECT p.Id
FROM 
    Products p
    INNER JOIN StaffMembers sm ON p.CreatedById = sm.Id AND sm.IsDeleted = 0
    INNER JOIN ProductCategories pc ON p.Id = pc.ProductId AND pc.IsDeleted = 0
WHERE p.DateCreated > '01-MAY-2021'

现在的逻辑读取数StaffMembers为 13,行数仍为 219。

执行计划

查询返回的记录数完全相同。从执行计划来看,索引扫描所用的StaffMembers完全一样。那么,为什么第二个查询的逻辑读取更高呢?

标签: sqlsql-server

解决方案


在此处添加更多细节,这对于评论来说太长了。

在第二个查询的执行计划中,选择select运算符。查看属性(或查看鼠标悬停弹出窗口)并注意估计的子树成本为 8.1;这是 SQL Server 对涉及多少工作的猜测,它高于默认阈值 5,因此(通常)这意味着它将考虑并行计划;并非总是如此,查询的某些元素可以强制执行串行计划,但通常情况下。

子树成本

在两个表之间选择了一种merge连接方法,并且操作员的输入需要排序输入,因此工作分配给多个线程。

如果您选择索引扫描运算符StaffMembers并查看属性,请注意下面actual I/O statistics是您观察到的逻辑读取以及它们如何分布在所有线程中。

逻辑读

鉴于查询在 <1 秒内完成,因此可能不需要并行,只是因为并行性的成本阈值设置得太低(这是 SQL Server 老化默认值之一,应该真正修改)。推荐值介于 40-60 之间。

当然,查询是对 和 进行表扫描,Products并且ProductCategories一些额外的支持索引将是有益的,并有助于通过更好的统计数据来提高估计成本。


推荐阅读