在以下查询计划中 - https://www.brentozar.com/pastetheplan/?id=H1dwOCHed(它有 3 个部分,最后一个是问题),最底部有一个节点消耗 37% 的资源. 这是实际的查询计划,而不是估计的查询计划。但是,当通过 Set Statistics IO 查看逻辑读取时,它引用的表根本不显示。这包括 ActivityFeedTeamCache 和 ActivityFeedCache 的 2 个部分。
过去,我已经能够使用逻辑读取作为性能的一个很好的代理。减少逻辑读取,并且您为性能做了正确的事情。
但是,由于在这种情况下,对于最差的块(ActivityFeedTeamCache、ActivityFeedCache、Locales)没有逻辑读取,那么测试性能的好代理是什么?只是实际执行计划中的成本百分比下降了吗?
即使在实际执行计划中,成本百分比仍然只是一个估计值。您需要查看此处的行源级别统计信息,以了解每个步骤花费了多少时间。
从 XML 来看,274 毫秒用于节点 7 的哈希连接点,其中 72 毫秒只是
Pk_TeamMembers
(节点 8)的集群扫描,35 毫秒是左半连接(节点 9)。这意味着仅执行 Hash Join 步骤就花费了高达 167 毫秒(可能为 263,600 行分配内存Pk_TeamMembers
)。看起来您之前已经尝试过定位此联接:
您可能想要对此索引执行(外部)嵌套循环。查询规划器决定使用哈希联接,因为它认为您将从该联接的另一端获得 59000 行,而实际上您得到 3。
你有选择
提示看起来像
由于驱动过滤器的复杂性,第二个选择将特别困难。一种方法是插入与您的主要驱动过滤器匹配的行,然后在您的主查询中加入此临时表。在这里,您似乎需要先将 5 个表中的 3 个连接在一起才能
@userId@
公平地利用您的过滤器:您还可以在 TeamMembers 表上进行键查找,这会消耗 14% 的执行时间。你应该尝试创建一个更好的转换索引来避免执行计划上的这种运算符。
例如,可以在 INCLUDE 中添加的缺失列是IsSiemensOnsiteAdmin
此外,您应该考虑修改此代码以使用 CTE 代替对不同列执行 2 次相同的查询