次のような大きなテーブルに対するクエリがあります。
declare @myIdParam int = 1
select *
from myTable
where (@myIdParam is null or myTable.Id = @myIdParam)
Where句には、このような同様の条件がいくつかあり、結合も多数ありますが、これは要約です。
事実上、@ myIdParamがnullの場合、このパラメーターを使用して結果を制限する必要はありません。
私はDBプロではありませんが、私のテストから、このNULLチェックはすべてのレコードに対して行われ、どのような方法でも最適化されていないようです。
Nullチェックを削除し、パラメーターがnullではないと想定すると、クエリはすぐに返されます。それ以外の場合は、最大10秒かかります。
これを最適化する方法はありますか?そのため、チェックは実行時に一度だけ行われますか?
1つの方法は、nullチェックを使用してオプションでwhere句のその部分を追加する動的SQLを使用することです。
declare @myIdParam int = 1
declare @vc_dynamicsql varchar(max)
set @vc_dynamicsql = 'select * from myTable where 1=1'
if @myIdParam is not null
set @vc_dynamicsql = @vc_dynamicsql + ' and myTable.Id = @myIdParam'
EXECUTE sp_executesql @vc_dynamicsql
たとえば、列「ISNULL(@var、table.col)」の周りに関数を置くと、SQLのインデックスを使用する機能が削除されます。これを単一のクエリに保持したい場合は、これが本当に最もパフォーマンスの高いオプションです。
@var IS NULL or @var = table.col
それ以外の場合は、2つのオプションがあります。 1つ目は動的SQLであり、@ Mystagogueの答えで十分です。それ以外の場合は、次のような2つのクエリを入力できます。
IF @var is NULL
SELECT * FROM table
ELSE
SELECT * FROM table WHERE @var = col
この形式と動的SQLの両方で、実際にはクエリごとに異なるクエリプランが得られます(パフォーマンスが向上する可能性があります)。
まあ、あなたはできます:
_declare @myIdParam int = 1;
select *
from myTable
where nullif(@myIdParam, myTable.Id) is null;
_
ただし、nullif()
関数は基本的にcase
のラッパーであることを覚えておいてください。魔法のようにOR
を排除してクエリを高速化するのは、特効薬ではありません。