SQL Serverに、記述されたクエリ条件を強制的に実行しますか?


14

私はSQL Server 2008 R2を使用していますが、この疑似クエリ(SP)があります:

select ...
from ...
WHERE    @LinkMode IS NULL
     AND (myColumn IN (...very long-running query...))
     ...
     ...

問題は、クエリを実行するのに非常に長い時間がかかること@LinkMode=2です。

お気づきのように、@ LinkModeがnullの場合にのみ長時間実行クエリを実行する必要がありますが、ここではそうではありません。私の場合、@ LinkMode = 2!

ただし、次のように変更すると:

 select ...
    from ...
    WHERE    1=2
         AND (myColumn IN (...very long time exeted query...))
     ...
     ...

SP 高速で実行されます。

以前に、オプティマイザー条件の順序を最適化できることを聞いたことがあります。

だから私は尋ねる:

  • オプティマイザが別のルートを選択した場合でも、次のことを確認するよりも高速なのは何=nullですか?私が意味する、私はそのチェックが考えるif a==nullあるずっと速く、他の長いクエリを実行するよりも...

  • どのように私がすることができます強制、私はそれ(同じ順序)書いたとして、クエリを実行するために、SQL Serverの?

回答:


22

あなたは「キャッチオールクエリ」トラップに陥っています。これは、ゲイルショーによってここで非常によく説明されています

問題を要約すると、SQL Serverは、コンパイル後にクエリプランをキャッシュし、その後のコンパイルの前に一致するクエリプランのキャッシュをチェックすることにより、クエリコンパイルの大きなオーバーヘッドを最適化します。ここで発生する「一致」は純粋にテキストであるため、変数の実際の値はこれに影響しません。

それは99%の時間で良いですが、場合によっては悪いです。それの悪いSQLコンパイラが作る必要があるため、そのCなどで短絡IF文のようこれは、うまく動作しないかのように、誰かの試みは、WHERE句を構築する際にある一つのケース1をにかかわらず動作するクエリプランをパラメーター値が実際に何であり、WHERE句でこれらの「賢い」論理スイッチング条件を処理できる唯一の方法は、テーブル全体をスキャンし、行をフィルタリングする単純なブルートフォース計画を作成することです、インデックスを活用せずに。

驚くことではありませんが、これにより、パラメーター/変数の値が何であっても、均一に遅くなります。


8

特定のシーケンスで句条件をSQLサーバーに強制的に実行させる方法は保証されていません。オプティマイザーは常に、適切と思われる順序でそれらを評価します。

あなたができることは次のようなものです:

IF @LinkMode IS NULL
BEGIN
    select ...
    from ...
    WHERE (myColumn IN (...very long time exeted query...))
         ...
         ...
END
ELSE
BEGIN
    select ...
    from ...
    WHERE ...
         ...
END

3

オプションの場合は、IFステートメントを使用して、適切な形式のクエリを実行します。また、SQLでは、dbエンジンに実行方法ではなく実行方法を指示します。最初から最後まで実行されません。それが何をするかを正確に予測することは困難です。あなたはおそらくこれを知っています;)


2

その場合、クエリオプティマイザーは実行時に実際の値を取得する必要があるため、ダイナミックSQLもおそらく機能します(間違っている場合は修正してください、実際はわかりませんが、同様の状況でそれを使用することを覚えているようです)。ただし、IF / ELSE句は最も必要なものを提供するという点で、私はこの他のユーザーと一緒にいます。これは、必要なことを正確に行う最も簡単で簡単なソリューションだからです。

まだ使用していない場合の将来の参照用に、動的SQLの実例が記載された恐ろしくsiteいサイトを、たとえばhttp://sqlusa.com/bestpractices/dynamicsql/で見つけることができます。


1

IF / ELSE構文をお勧めします。何らかの理由で機能しない場合は、WITH RECOMPILEオプションの使用をいつでも検討できます。


「if / else構文」がどのように見えるかについて詳しく説明していただけますか?:D
jcolebrand

OPTION(RECOMPILE)を使用することをお勧めします。毎回理想的なプランが生成されるためです-コンパイルの遅延によりオーバーヘッドが追加されますが、この場合は全体的に優れていると思います。
SqlRyan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.