带有位图筛选器的查询计划有时可能很难读取。从BOL有关分区流的文章(重点是我的):
Repartition Streams运算符使用多个流并产生多个记录流。记录内容和格式不变。如果查询优化器使用位图过滤器,则会减少输出流中的行数。
此外,有关位图过滤器的文章也很有帮助:
分析包含位图筛选的执行计划时,重要的是要了解数据如何流经计划以及在何处应用筛选。位图过滤器和优化的位图是在哈希联接的构建输入(维度表)侧创建的;但是,实际过滤通常是在Parallelism运算符内完成的,该运算符在哈希联接的探测输入(事实表)侧。但是,当位图筛选器基于整数列时,可以将筛选器直接应用于初始表或索引扫描操作,而不是并行操作符。此技术称为行内优化。
我相信这就是您在查询中所观察到的。可以提出一个相对简单的演示,以显示重新分配流运算符减少基数估计,即使位图运算符IN_ROW
违反事实表也是如此。数据准备:
create table outer_tbl (ID BIGINT NOT NULL);
INSERT INTO outer_tbl WITH (TABLOCK)
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values;
create table inner_tbl_1 (ID BIGINT NULL);
create table inner_tbl_2 (ID BIGINT NULL);
INSERT INTO inner_tbl_1 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
INSERT INTO inner_tbl_2 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
这是您不应运行的查询:
SELECT *
FROM outer_tbl o
INNER JOIN inner_tbl_1 i ON o.ID = i.ID
INNER JOIN inner_tbl_2 i2 ON o.ID = i2.ID
OPTION (HASH JOIN, QUERYTRACEON 9481, QUERYTRACEON 8649);
我上传了计划。看一下附近的操作员inner_tbl_2
:
您可能还会发现Paul White的“ 在可空列上的哈希连接”中的第二项测试很有帮助。
行减少的应用方式存在一些不一致之处。我只能在至少有三个表的计划中看到它。但是,通过正确的数据分配,减少预期行似乎是合理的。假设事实表中的联接列具有很多重复的值,而这些重复值在维度表中不存在。位图筛选器可能会在这些行到达联接之前消除它们。对于您的查询,估计值一直减少到1。如何在哈希函数之间分配行提供了一个很好的提示:
基于此,我怀疑您对该Object1.Column21
列有很多重复的值。如果重复的列恰好不在统计直方图中,Object4.Column19
则SQL Server可能会得出基数估计非常错误的信息。
我认为您应该担心,可能可以提高查询的性能。当然,如果查询满足响应时间或SLA要求,则可能不值得进一步研究。但是,如果您希望进一步调查,可以做一些事情(除了更新统计信息),以了解如果查询优化器具有更好的信息,是否会选择更好的计划。你可以把结果之间的连接Database1.Schema1.Object10
,并Database1.Schema1.Object11
与到一个临时表看,如果你继续得到嵌套循环联接。您可以将联接更改为a,LEFT OUTER JOIN
这样查询优化器就不会减少该步骤的行数。您可以MAXDOP 1
在查询中添加提示以查看会发生什么。你可以用TOP
以及派生表来强制联接最后执行,或者您甚至可以从查询中注释掉联接。希望这些建议足以使您入门。
关于问题中的连接项,极不可能与您的问题有关。该问题与行估计不佳无关。它与并行的竞争条件有关,竞争条件导致在后台的查询计划中要处理太多行。在这里,您的查询似乎没有做任何额外的工作。