为什么批处理模式窗口合计会产生算术溢出?


11

以下查询在具有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.

完整脚本

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

查询计划

这是一个带注释的估算查询计划(“粘贴计划”中的完整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 */) 

Answers:


6

多个评论者已经能够重现此问题。我们最初以为SQL Server 2017 CU10解决了此问题,但随后发现该错误可以在我们尝试的所有SQL Server版本(包括CU10)中都再现。但是,一些评论者观察到机会元素,其中同一脚本并不总是触发错误。

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

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

响应是:

该问题已在SQL Server 2019 CTP 2.1中修复,也将很快在Azure SQL数据库中修复。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.