web-dev-qa-db-fra.com

Pourquoi l'agrégat de la fenêtre de mode par lots rend-il débordement arithmétique?

La requête suivante effectue une table Windowed SUM sur une table de colonne avec 1500 total rows, chacun d'entre eux a la valeur 0 ou 1, et il déborde du type de données INT. Pourquoi cela arrive-t-il?

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.

Script complet

Voir ce fichier pour un script de reproduction entièrement contenue.

plan de requête

Voici un plan de requête estimé annoté ( XML complet sur coller le plan ).

enter image description here

requêtes similaires qui exécutent avec succès

Si l'une des modifications suivantes est effectuée, l'erreur ne se produit pas:

  • Utilisez le drapeau de trace 8649 Pour préférer un plan parallèle quel que soit le seuil de coût du parallélisme
  • Utilisez le drapeau de trace 9453 Pour désactiver le mode batch
  • Utilisez la fonction d'agrégation COUNT au lieu de la fonction SUM
  • Retirer le WHERE x.rank = 1 prédicat

Par exemple, cette requête s'exécute avec succès:

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 */) 
11
Geoff Patterson

Plusieurs commentateurs ont été en mesure de reproduire ce problème. Nous avons initialement pensé que SQL Server 2017 CU10 a résolu le problème, mais a ensuite constaté que l'erreur peut être reproduite dans toutes les versions de SQL Server que nous avons essayé, y compris CU10. Cependant, certains commentateurs ont observé un élément de chance où le même script n'a pas toujours déclenché l'erreur.

Étant donné qu'il n'y a pas de moyen logique qui calculant une somme sur un ensemble de nombres non négatifs dont la somme maximale possible est de 1 500 peut déborder un entier 32 bits, nous pensons que ceci est un bogue dans l'opérateur d'agrégat de la fenêtre de mode Batch. Être un nouvel opérateur dans SQL Server 2016, il est raisonnable de supposer qu'il pourrait encore y avoir des cas de bord à l'extérieur.

Voici le rapport de bogue que nous avons déposé avec Microsoft.

La réponse était:

Ceci est corrigé dans SQL Server 2019 CTP 2.1 et sera également corrigé dans la base de données Azure SQL.

6
Geoff Patterson