ケースステートメントの最適化について、今日、同僚と興味深いディスカッションがありました。個別のwhen句として、重複する基準を持つケースステートメントを残すのが良いのか、それとも、重複するステートメントごとに入れ子のcaseステートメントを作成するのが良いのか、です。
例として、列aと列bの2つの整数フィールドを持つテーブルがあるとします。 2つのクエリのどちらがよりプロセッサフレンドリーになりますか?ネストされたステートメントを使用して一度だけa = 1かa = 0かを評価しているので、これはプロセッサにとってより効率的ですか、それともネストされたステートメントを作成するとその最適化が無駄になりますか?
ケースステートメントの複数の基準:
Select
case
when a=1 and b=0 THEN 'True'
when a=1 and b=1 then 'Trueish'
when a=0 and b=0 then 'False'
when a=0 and b=1 then 'Falseish'
else null
end AS Result
FROM tableName
入れ子のcaseステートメント:
Select
case
when a=1 then
case
when b=0 then 'True'
when b=1 then 'Trueish'
end
When a=0 then
case
when b=0 then 'False'
when b=1 then 'Falseish'
end
else null
end AS Result
FROM tablename
誰かがやって来て、これらの操作が実際にCPUでどのように処理されるか、またはこれらの2つのクエリ間でどのように異なる命令が生成されるかの詳細を掘り下げるかもしれません。 しかし、実用的な観点からは、大きな違いはないようです。
これにより、1と0の値のいくぶん任意の分布で、2ビット列の1000万行のテーブルがロードされます。
CREATE DATABASE [239583];
GO
USE [239583];
GO
SELECT TOP 10000000
CASE WHEN v.number % 2 = 0 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS a,
CASE WHEN v.number % 2 = 1 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS b
INTO dbo.TableName
FROM master.dbo.spt_values v
CROSS JOIN master.dbo.spt_values v2
CROSS JOIN master.dbo.spt_values v3;
次に、SSMSに実行後に結果を破棄するように指示しました(クエリ->クエリオプション->グリッド->実行後に結果を破棄)。これは、SSMSが1と0の20mm行のロードをクラッシュするのを待つ時間がないためです。
次に、このコードを実行しました:
SET STATISTICS IO, TIME ON;
Select
case
when a=1 and b=0 THEN 'True'
when a=1 and b=1 then 'Trueish'
when a=0 and b=0 then 'False'
when a=0 and b=1 then 'Falseish'
else null
end
FROM tableName;
Select
case
when a=1 then
case
when b=0 then 'True'
when b=1 then 'Trueish'
end
When a=0 then
case
when b=0 then 'False'
when b=1 then 'Falseish'
end
else null
end
FROM tablename;
私の典型的な実行では、私のマシンでは次のようなCPU出力があります。
Query 1: CPU time = 2141 ms, elapsed time = 2191 ms.
Query 2: CPU time = 2359 ms, elapsed time = 2461 ms.
時々、それらはわずかに等しいか、2番目のクエリがわずかに速いですが、これらは、このクエリを実行するだけでなく、ラップトップのCPUの通常のバリエーションであり、他のものを実行していると思います。