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)
完整脚本
查询计划
成功执行的类似查询
如果进行以下任何修改,则不会发生错误:
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)
多个评论者已经能够重现这个问题。我们最初认为 SQL Server 2017 CU10 解决了该问题,但后来发现该错误在我们尝试的所有 SQL Server 版本中都可以重现,包括 CU10。然而,一些评论者观察到一个偶然因素,即相同的脚本并不总是触发错误。
由于在一组最大可能和为 1,500 的非负数上计算和会溢出 32 位整数,因此没有逻辑方法,我们认为这是批处理模式窗口聚合运算符中的错误。作为 SQL Server 2016 中的新运算符,可以合理地假设可能仍有一些边缘情况需要解决。
回应是:
此问题已在 SQL Server 2019 CTP 2.1 中修复,并且很快也会在 Azure SQL 数据库中修复。