5

さまざまなテーブルのデータ行を検索するために、複数の null 許容パラメーターを使用する "検索ストアド プロシージャ" が多数あります。それらは通常、次のように構築されます。

SELECT      *
 FROM       Table1 T1
 INNER JOIN Table2 T2
     ON     T2.something = T1.something
 WHERE      (@parameter1 IS NULL OR T1.Column1 = @parameter1)
        AND (@parameter2 IS NULL OR T2.Column2 = @parameter2)
        AND (@parameter3 IS NULL OR T1.Column3 LIKE '%' + @parameter3 + '%')
        AND (@parameter4 IS NULL OR T2.Column4 LIKE '%' + @parameter4 + '%')       
        AND (@parameter5 IS NULL OR T1.Column5 = @parameter5)

これは最大 30 ~ 40 個のパラメーターに対して実行できます。私たちが気づいたことは、parameter1 のみが提供されている場合でも、実行プランは他のテーブルのインデックス スキャンを通過するため、クエリが大幅に (数秒) 遅くなる可能性があることです。テストでは、WHERE ステートメントの最初の行のみを保持することでクエリが瞬時に実行されることが示されています。

  1. ショートカットは不可能だと読みましたが、より効率的なクエリを構築するための回避策や方法はありますか?

  2. 現在、同じ SELECT/FROM/JOINS の異なるバージョンを使用することでこの問題を回避していますが、WHERE 句に異なるパラメーター セットを使用し、渡されるパラメーターに応じて適切な選択ステートメントを選択しています。これは長く、面倒で、維持するのが困難です。

4

1 に答える 1

4

SQL Server のクエリ プランはコンパイルされ、再利用できるように保存されます。SQL Server がパラメータがであるnullことを認識したとしても、パラメータがnot null.

クエリ ヒントoption (recompile)は SQL Server 2005 で導入されましたが、ここにあるクエリの種類に実際に影響を与えたのは SQL Server 2008 まででした。

クエリが毎回再コンパイルされると、クエリ プラン キャッシュに保存されないため、SQL Server はパラメータに対するチェックを自由に最適化できますnull

詳しくはこちらをご覧くださいT-SQL の動的検索条件

クエリ プランの違いを確認するためにテストできるサンプル コード。SP への最初の呼び出しでインデックス シークが実行され、2 回目の呼び出しでクラスター化インデックス スキャンが実行されます。

create table T
(
  ID int identity primary key,
  Col1 int,
  Col2 int
);

go

create index IX_T on T(Col1);

go

create procedure GetT
  @Col1 int,
  @Col2 int
as

select ID
from T
where (Col1 = @Col1 or @Col1 is null) and
      (Col2 = @Col2 or @Col2 is null)
option (recompile);

go

exec GetT 1, null
exec GetT 1, 1
于 2013-04-06T15:26:41.110 に答える