缓慢的并行 SQL Server 查询,串行几乎是即时的

SEa*_*986 2 parallelism sql-server-2016 query-performance

我有一个 SQL Server 查询如下(混淆):

UPDATE  [TABLE1]
SET     [COLUMN1] = CAST('N' AS CHAR(1))
FROM    [TABLE1]
WHERE   (COLUMN1 = '2' AND COLUMN2 IN('VAL1', 'VAL2', 'VAL3')) OR 
        (COLUMN1 <> 'N' AND (
                                    SELECT  COUNT(*)
                                    FROM    TABLE2 wle
                                            JOIN TABLE3 wl 
                                                    ON wl.COLUMN3 = wle.COLUMN3
                                    WHERE   TABLE1.COLUMN4 = wle.COLUMN4 AND 
                                            (wl.COLUMN5 = '1' OR wl.COLUMN6 = '1') AND 
                                            wle.COLUMN7 = (
                                                            SELECT  MIN(alias.COLUMN7)
                                                            FROM    TABLE2 AS alias
                                                            WHERE   TABLE1.COLUMN4 = alias.COLUMN4
                                                            )
                                ) > 0
                                            
        )
Run Code Online (Sandbox Code Playgroud)

我们刚刚将我们的(测试)服务器从 SQL Server 2014 SP3 升级到 SQL Server 2016 SP2。

因此,上述查询的性能似乎已经下降。

服务器在SQL Server 2014的时候,数据库兼容级别是120,现在在SQL Server 2016,数据库兼容级别还是120,但是我试过110120和130的查询,结果都是一样的.

当我运行时sp_whoisactive,我可以看到 wait_info(48847425ms)CXCONSUMER提示查询一直在等待CXCONSUMER最后一次48847425ms(814 分钟) 查询当前已运行 13:34:07.587。

等待信息表明该查询已经等待CXCONSUMER了大多数(如果不是全部)执行时间。

这对我来说表明并行性存在一些问题,因此我使用提示运行查询OPTION (MAXDOP 1)并在可接受的时间内完成(大约 30 秒)

计划形状如下。

在此处输入图片说明

MAXDOP 1查询的计划形状如下:

在此处输入图片说明

(没有并行操作符的相同计划)

当我在启用实时执行计划的情况下运行并行查询时,以绿色突出显示的运算符(聚集索引扫描打开TABLE2)显示 100%,但它的执行时间继续计时。

以红色突出显示的运算符(Clustered Index Scan on TABLE1)在 180,215 的 4 行上“卡住”。

什么可能导致这个问题?在我的脑海中,我认为这是并行性倾斜(不均匀的工作量),但鉴于串行查询在不到一分钟的时间内完成,我会认为即使查询并行但只使用一个线程,它仍然会在接近的时间内完成串行查询。此外,鉴于实时计划似乎显示红色聚集索引扫描根本没有进展,我不确定发生了什么。

处理器和 I/O 关联设置为自动

我发现这篇文章描述了类似的行为,尽管文章的目的似乎表明 CXCONSUMER 不一定是良性等待,并且没有说明如何/是否可以修复它。

在修复它方面,我知道可以以更有效的方式重新编写代码(可以将查询COUNTMIN子查询都选择到变量中),但不幸的是,更改查询不是我的选择。我可以强制MAXDOP提示,但同样,这意味着更改代码,也许我可以用计划指南强制它,尽管这种强制优化器的做法通常是不可取的?

是什么导致了这个问题?

为什么查询在 SQL Server 2016 中运行缓慢?

为什么 TABLE1 上的聚集索引扫描在 180,215 的 4 行上“卡住”?

有没有办法在不更改代码的情况下解决这个问题?

Pau*_*ite 5

有没有办法在不更改代码的情况下解决这个问题?

创建以下索引以消除急切索引假脱机:

-- Give this index a better name
CREATE INDEX i ON dbo.TABLE2 (COLUMN4, COLUMN7) INCLUDE (COLUMN3);
Run Code Online (Sandbox Code Playgroud)

有了这个,你应该得到一个类似于以下的计划:

在此处输入图片说明

一旦您为优化器提供了良好的索引,问题中描述的其他问题几乎肯定会消失。

这是可能的(虽然不太可能)从你的查询患有未被发现查询内并行的死锁(IQPD)。需要进行非常详细的调查才能确认这一点。绝大多数 IQPD都被检测到,然后可以通过将交换缓冲区溢出到tempdb来解决。未检测到的 IQPD 将导致查询永远卡住。