A consulta a seguir executa uma janela SUM
em uma tabela columnstore com 1500 total rows
, cada uma com o valor 0 ou 1, e transborda o INT
tipo de dados. Por que isso está acontecendo?
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.
Roteiro completo
Veja este arquivo para um script de reprodução totalmente contido.
Plano de consulta
Aqui está um plano de consulta estimado anotado ( XML completo em Colar o Plano ).
Consultas semelhantes executadas com sucesso
Se alguma das seguintes modificações for feita, o erro não ocorrerá:
- Use o sinalizador de rastreamento
8649
para preferir um plano paralelo, independentemente do limite de custo para paralelismo - Use o sinalizador de rastreamento
9453
para desativar o modo em lote - Use a
COUNT
função de agregação em vez daSUM
função - Remova o
WHERE x.rank = 1
predicado
Por exemplo, esta consulta é executada com sucesso:
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 */)
Vários comentaristas conseguiram reproduzir esse problema. Inicialmente, pensamos que o SQL Server 2017 CU10 resolveu o problema, mas descobrimos que o erro pode ser reproduzido em todas as versões do SQL Server que tentamos, incluindo CU10. No entanto, alguns comentaristas observaram um elemento de chance em que o mesmo script nem sempre acionou o erro.
Como não há uma maneira lógica de calcular uma soma em um conjunto de números não negativos cuja soma máxima possível é 1.500 possa estourar um inteiro de 32 bits, acreditamos que isso seja um bug no operador de agregação de janela de modo de lote. Sendo um novo operador no SQL Server 2016, é razoável supor que ainda pode haver alguns casos extremos a serem resolvidos.
Aqui está o relatório de bug que arquivamos com a Microsoft.
A resposta foi: