integer
変数と比較しているという事実は関係ありません。
のプランにはCOUNT
常にCONVERT_IMPLICIT(int,[ExprNNNN],0))
where ExprNNNN
があり、はの結果を表す式のラベルですCOUNT
。
私の想定では、のコードはCOUNT
最終的にはと同じコードを呼び出すだけでCOUNT_BIG
あり、キャストはそのbigint
結果をに変換するために必要であるというものint
でした。
実際COUNT_BIG(*)
、クエリプランでもと区別されていませんCOUNT(*)
。どちらもとして表示されScalar Operator(Count(*))
ます。
COUNT_BIG(nullable_column)
は実行計画でと区別されますCOUNT(nullable_column)
が、後者は依然として暗黙的ににキャストされint
ます。
これが事実であることを示すいくつかの証拠を以下に示します。
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)
これは私のデスクトップで実行するのに約7分かかり、次を返します
メッセージ8115、レベル16、状態2、行1
式をデータ型intに変換する算術オーバーフローエラー。
警告:Null値は、集計またはその他のSET操作によって削除されます。
これは、がオーバーフローCOUNT
した後int
(2147483647)、最後の行(2150000000)がCOUNT
オペレーターによって処理され、NULL
返されたというメッセージが表示された後も、が継続している必要があることを示しています。
比較のために置き換えCOUNT
て表現をSUM(CASE WHEN N < 2150000000 THEN 1 END)
返します
メッセージ8115、レベル16、状態2、行1
式をデータ型intに変換する算術オーバーフローエラー。
ANSI
に関する警告なしNULL
。この場合、行自体が行2,150,000,000に達する前の集計中にオーバーフローが発生したと結論付けます。
ScalarOperator
SSMSのプロパティウィンドウに表示される値を見ていました。