2

ストアドプロシージャを使用します。

WHERE句では、ほとんどの入力がデフォルトでNullになっていることをクエリオプティマイザーが認識しているため、短絡(OR)を使用して実行を高速化します。これにより、クエリを柔軟かつ高速にすることができます。

WHERE句にテーブル値パラメーターを追加しました。レポートの実行時間は150ミリ秒から450ミリ秒に増加し、読み取りは70,000から200,000になりました。

...
WHERE
    --Integer value parameters
    AND ((@hID is Null) OR (h.ID = @hID))
    AND ((@dID is Null) OR (d.ID = @dID))
    AND ((@mID is NULL) OR (m.ID = @mID))
    --New table value parameter 
    --Execute, Processing time and read's increased. 
    --No additional JOIN added.
    AND (NOT EXISTS (SELECT Null FROM @rIDs) OR r.ID IN (SELECT r FROM @rIDs))

NOT EXISTSを短絡したり、このクエリを高速化するにはどうすればよいですか?クエリを実行する前に、BIT値を追加し、行がテーブル値パラメーターに含まれているかどうかを確認してみました。私が見つけた唯一の方法は、2つのクエリを実行し、一方を他方に対して実行することです。大量のクエリを変更したり、複数のテーブル値パラメーターをミックスに追加したりする必要がある場合は、あまり良くありません。

前もって感謝します。

編集:

テーブル値パラメーターの比較:

    AND (NOT EXISTS (SELECT Null FROM @rIDs) OR r.ID IN (SELECT r FROM @rIDs))

および整数パラメータ:

    AND ((@rID) OR (r.ID = @rID))

TVPを0行、整数パラメーターをnullでコンパイルした後、同様の実行速度を示しました。クエリオプティマイザーが正しいマナーで短絡していて、以前の比較が正しくなかったと思います。実行計画では、上記のコストを55%と45%に分割しますが、これは許容範囲です。TVPの行数が増えても分割は変わりませんが、ディスクから読み取る必要のあるページが増えるため、レポートの生成にかかる時間が長くなります。面白い。

4

3 に答える 3

0
if exists (select * from @rIDs)
    begin
    .... -- query with TVP
    end
else
    begin
    .... -- query without TVP
    end

これにより、クエリごとに個別の実行プランが可能になります。

于 2013-01-09T15:02:14.927 に答える
0

テーブル変数を使用しているようです。一時テーブルを使用し、基準に使用している列にインデックスを付ける場合 (例では r)、テーブル スキャンを回避します。ただし、これにより複数のステップのプロセスになりますが、その見返りは非常に大きくなる可能性があります。

質問をより具体的にするために、例の最後の行を AND EXISTS (SELECT r FROM @rIDs WHERE r = r.ID AND NOT r IS NULL) に変更できます。

実行計画を投稿していただければ、より適切な回答を差し上げることができます。[推定実行計画の表示] をクリックし、実行計画を右クリックして、[実行計画に名前を付けて保存...] を選択します。

于 2013-01-09T15:10:13.790 に答える