为什么批处理模式窗口聚合产量算术溢出?

Geo*_*son 12 sql-server columnstore window-functions batch-mode sql-server-2016

以下查询SUM对列存储表执行窗口化处理1500 total rows,每个表的值为 0 或 1,并溢出INT数据类型。为什么会这样?

SELECT a, p, s, v, m, n,
    SUM(CASE WHEN n IS NULL THEN 0 ELSE 1 END)
        OVER (PARTITION BY s, v, a ORDER BY p) AS lastNonNullPartition
FROM (
    SELECT a, p, s, v, m, n,
        RANK() OVER (PARTITION BY v, s, a, p ORDER BY m) AS rank
    FROM #t /* A columnstore table with 1,500 rows */
)  x
WHERE x.rank = 1
--Msg 8115, Level 16, State 2, Line 1521
--Arithmetic overflow error converting expression to data type int.
Run Code Online (Sandbox Code Playgroud)

完整脚本

有关完全包含的复制脚本,请参阅此文件。

查询计划

这是一个带注释的估计查询计划(粘贴计划的完整 XML)。

在此处输入图片说明

成功执行的类似查询

如果进行以下任何修改,则不会发生错误:

  • 8649无论并行性的成本阈值如何,使用跟踪标志来首选并行计划
  • 使用跟踪标志9453禁用批处理模式
  • 使用COUNT聚合函数代替SUM函数
  • 删除WHERE x.rank = 1谓词

例如,此查询成功执行:

SELECT a, p, s, v, m, n,
    SUM(CASE WHEN n IS NULL THEN 0 ELSE 1 END)
        OVER (PARTITION BY s, v, a ORDER BY p) AS lastNonNullPartition
FROM (
    SELECT a, p, s, v, m, n,
        RANK() OVER (PARTITION BY v, s, a, p ORDER BY m) AS rank
    FROM #t /* A columnstore table with 1,500 rows */
)  x
WHERE x.rank = 1
OPTION (QUERYTRACEON 9453/* Disable batch mode */) 
Run Code Online (Sandbox Code Playgroud)

Geo*_*son 7

多个评论者已经能够重现这个问题。我们最初认为 SQL Server 2017 CU10 解决了该问题,但后来发现该错误在我们尝试的所有 SQL Server 版本中都可以重现,包括 CU10。然而,一些评论者观察到一个偶然因素,即相同的脚本并不总是触发错误。

由于在一组最大可能和为 1,500 的非负数上计算和会溢出 32 位整数,因此没有逻辑方法,我们认为这是批处理模式窗口聚合运算符中的错误。作为 SQL Server 2016 中的新运算符,可以合理地假设可能仍有一些边缘情况需要解决。

这是我们向 Microsoft 提交的错误报告。

回应是:

此问题已在 SQL Server 2019 CTP 2.1 中修复,并且很快也会在 Azure SQL 数据库中修复。