以下查询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 */)
多个评论者已经能够重现此问题。我们最初认为 SQL Server 2017 CU10 解决了这个问题,但后来发现该错误可以在我们尝试的所有 SQL Server 版本中重现,包括 CU10。然而,一些评论者观察到一个偶然因素,即同一脚本并不总是触发错误。
因为没有逻辑方法计算一组非负数的总和,其最大可能总和为 1,500 会溢出 32 位整数,我们认为这是批处理模式窗口聚合运算符中的错误。作为 SQL Server 2016 中的新运算符,可以合理地假设可能仍有一些边缘情况需要解决。
这是我们向 Microsoft 提交的错误报告。
回应是: