6

一部の列で動的にする必要があるクエリがあります。つまり、パラメーターを取得し、その値に応じて Where 句でフェッチする列を決定します。「CASE」式を使用してこのリクエストを実装しました。

(CASE @isArrivalTime WHEN 1 THEN ArrivalTime ELSE PickedupTime END) 
>= DATEADD(mi, -@TZOffsetInMins, @sTime) 
 AND (CASE @isArrivalTime WHEN 1 THEN ArrivalTime ELSE PickedupTime END) 
 < DATEADD(mi, -@TZOffsetInMins, @fTime)

@isArrivalTime = 1次にArrivalTime列を選択した場合は、列を選択しPickedupTimeました。にクラスター化インデックスArrivalTimeと に非クラスター化インデックスがありますPickedupTime

@isArrivalTime = 1このクエリを ( とともに) 使用している場合、 のみを使用する場合に比べてパフォーマンスが大幅に低下することに気付きましたArrivalTime

クエリ オプティマイザが、この方法で適切にインデックスを使用\選択できないのではないでしょうか?

実行計画を比較したところCASE、インデックス スキャンで 32% の時間が無駄になっていることに気付きましたが、CASE ArrivalTime`) を使用しなかった場合、(just usedこのインデックス スキャンで無駄になったのは 3% だけでした。

この理由を知っている人はいますか?

4

2 に答える 2

3

2つの違いは、おそらくスキャンする必要がある行数が異なるためです。あなたのクエリは、より多くのテーブル間の結合の最終結果である可能性が高いためです。スキャンは、その名前が示すとおり、すべての行のスキャンであることに注意してください。行数の見積もりを計画で確認して、アイデアを出すことができます。

動的フィールドでフィルターを使用する場合 (大文字と小文字を使用するなど)、そのフィールドのインデックスはエンジンで使用できません。このような場合は、動的 SQL を使用して必要な正しい SQL を生成し、exec_sql を使用することをお勧めします。または、if ステートメントを使用して、適切なものを直接クエリします。

これは、動的 sql を使用するのに役立つ場合があります。その理由と方法について説明します。

http://www.sommarskog.se/dynamic_sql.html

于 2012-09-16T09:25:03.343 に答える
0

日時境界を設定してみてください:

declare @resSTime datetime
        ,@resFTime datetime

set @resSTime = DATEADD(mi, -@TZOffsetInMins, @sTime)
set @resFTime = DATEADD(mi, -@TZOffsetInMins, @fTime)

大文字と小文字を「または」に変更してみてください

( ArrivalTime >= @resSTime 
    and ArrivalTime < @resFTime 
    and @isArrivalTime = 1 )
or ( PickedupTime >= @resSTime 
    and PickedupTime < @resFTime 
    and @isArrivalTime <> 1 )
于 2012-09-18T08:04:31.303 に答える