Le fait que vous le compariez à une integer
variable n'est pas pertinent.
Le plan pour a COUNT
toujours un CONVERT_IMPLICIT(int,[ExprNNNN],0))
où ExprNNNN
est le libellé de l'expression représentant le résultat de la COUNT
.
Mon hypothèse a toujours été que le code pour COUNT
finit par appeler le même code que COUNT_BIG
et que le transtypage est nécessaire pour convertir le bigint
résultat de celui-ci en int
.
En fait, il COUNT_BIG(*)
n'est même pas distingué dans le plan de requête COUNT(*)
. Les deux apparaissent comme Scalar Operator(Count(*))
.
COUNT_BIG(nullable_column)
se distingue dans le plan d'exécution de COUNT(nullable_column)
mais ce dernier obtient toujours un cast implicite vers le bas int
.
Quelques preuves que c'est le cas se trouvent ci-dessous.
WITH
E1(N) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
) -- 1*10^1 or 10 rows
, E2(N) AS (SELECT 1 FROM E1 a, E1 b) -- 1*10^2 or 100 rows
, E4(N) AS (SELECT 1 FROM E2 a, E2 b) -- 1*10^4 or 10,000 rows
, E8(N) AS (SELECT 1 FROM E4 a, E4 b) -- 1*10^8 or 100,000,000 rows
, E16(N) AS (SELECT 1 FROM E8 a, E8 b) -- 1*10^16 or 10,000,000,000,000,000 rows
, T(N) AS (SELECT TOP (2150000000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS N FROM E16)
SELECT COUNT(CASE WHEN N < 2150000000 THEN 1 END)
FROM T
OPTION (MAXDOP 1)
Cela prend environ 7 minutes pour s'exécuter sur mon bureau et renvoie ce qui suit
Msg 8115, niveau 16, état 2, ligne 1
Erreur de dépassement arithmétique lors de la conversion de l'expression en type de données int.
Avertissement: la valeur nulle est éliminée par un agrégat ou une autre opération SET.
Ce qui indique que le COUNT
doit avoir continué après qu'un int
aurait débordé (à 2147483647) et la dernière ligne (2150000000) a été traitée par l' COUNT
opérateur conduisant au message de NULL
retour.
A titre de comparaison, remplacer l' COUNT
expression par des SUM(CASE WHEN N < 2150000000 THEN 1 END)
retours
Msg 8115, niveau 16, état 2, ligne 1
Erreur de dépassement arithmétique lors de la conversion de l'expression en type de données int.
sans ANSI
avertissement NULL
. D'où je conclus que le débordement s'est produit dans ce cas lors de l'agrégation elle-même avant que la ligne 2 150 000 000 ne soit atteinte.
ScalarOperator
valeur indiquée dans la fenêtre des propriétés SSMS.