El hecho de que lo esté comparando con una integer
variable es irrelevante.
El plan para COUNT
siempre tiene un CONVERT_IMPLICIT(int,[ExprNNNN],0))
dónde ExprNNNN
es la etiqueta para la expresión que representa el resultado de COUNT
.
Mi suposición siempre ha sido que el código para COUNT
simplemente termina llamando al mismo código COUNT_BIG
y el reparto es necesario para convertir el bigint
resultado de eso nuevamente int
.
De hecho, COUNT_BIG(*)
ni siquiera se distingue en el plan de consulta COUNT(*)
. Ambos aparecen como Scalar Operator(Count(*))
.
COUNT_BIG(nullable_column)
sí se distingue en el plan de ejecución, COUNT(nullable_column)
pero este último todavía tiene un reparto implícito de nuevo int
.
Alguna evidencia de que este es el caso está abajo.
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)
Esto demora aproximadamente 7 minutos en ejecutarse en mi escritorio y devuelve lo siguiente
Mensaje 8115, Nivel 16, Estado 2, Línea 1
Error de desbordamiento aritmético al convertir la expresión al tipo de datos int.
Advertencia: el valor nulo es eliminado por un agregado u otra operación SET.
Lo que indica que COUNT
debe haber continuado después de que int
se hubiera desbordado un (en 2147483647) y la última fila (2150000000) fue procesada por el COUNT
operador que condujo al mensaje de NULL
devolución.
A modo de comparación, reemplazando la COUNT
expresión con SUM(CASE WHEN N < 2150000000 THEN 1 END)
retornos
Mensaje 8115, Nivel 16, Estado 2, Línea 1
Error de desbordamiento aritmético al convertir la expresión al tipo de datos int.
sin ANSI
previo aviso NULL
. De lo cual concluyo que el desbordamiento ocurrió en este caso durante la agregación misma antes de alcanzar la fila 2,150,000,000.
ScalarOperator
valor que se muestra en la ventana de propiedades de SSMS.