2012-04-02 3 views
1

私はこのようになりますクエリがあります。悪いのパフォーマンスOR条件

SELECT * 
FROM A 
INNER JOIN B ON A.AId = B.AId 
WHERE A.ADate BETWEEN @Start and @End 
    or B.BDate BETWEEN @Start and @End 

両方のテーブルAとBが同じサイズであると行がたくさんあるし。実行プランは、インデックスシークを示していますが、インデックス全体をスキャンしているようです。

orandに変更すると、クエリが非常に高速になります。これは、orを計算するために両方のテーブルでテーブルスキャンを実行しなければ、orの結果を知ることができないためです。 andは簡単に2つの操作に分割されます。

私は、orの代わりにUNIONを使用することが可能であると述べていますが、ORの両方の条件が真である場合に重複する行が導入される可能性があります。

私は結合のサイズを減らし、両方のテーブルの完全な結合を防ぐことができるので、どのような解決方法がありますか?私はクエリを再構築することは可能ですが、この作業を行うことは可能ですが、クエリーのロジックが必要です(範囲内の日付または範囲内の日付と一致する項目を与えてください)。

答えて

0

おかげで、最後に私はUNION ALLを選んだ、と私は2つの選択の労働組合に基づいてクエリを細工:あなたはインライン表を使用して参加する前に、プレフィルタリング各テーブルについて何

1

UNIONは重複する行を導入しません。 UNION ALLは重複を導入する可能性があります。

SELECT * 
FROM A 
INNER JOIN B ON A.AId = B.AId 
WHERE A.ADate BETWEEN @Start and @End 

UNION 

SELECT * 
FROM A 
INNER JOIN B ON A.AId = B.AId 
WHERE B.BDate BETWEEN @Start and @End 

が速く、クエリのようになります。

は私がいることを想像するhttp://www.w3schools.com/sql/sql_union.asp

を参照してください。答えを

SELECT A.*, B.* 
FROM (SELECT AId AS Id FROM A WHERE A.ADate BETWEEN @Start and @End 
     UNION 
     SELECT BId AS Id FROM B WHERE B.BDate BETWEEN @Start and @End) AS FilteredIds 
INNER JOIN A ON A.AId = FilteredIds.Id 
INNER JOIN B ON B.BId = FilteredIds.Id 
+0

UNIONについての訂正をありがとう、私はそれを試してみます。私は少し重複していないことを確実にするために別個の並べ替えを心配していますが、それは私が見ている "または"の動作よりも速いかもしれません。 – Kekoa

+0

確かに。それがうまくいかない場合は、Mike Parkhillのアプローチに刺すようにしてください。 –

2

相互に排他的であるため、UNION ALLに重複は導入されません。

最初に、ADateが範囲内にあるすべての行を取得し、BDateが範囲内にある行を除外します。次に、BDateが範囲内にあるすべての行を取得します。これらの2つのセットの和集合は、論理的に、ADateまたはBDateをカバーする行のセットを生成します。中間を二重にカウントすることはありません(UNION ALLは重複を生成しません)。あなたがこの論理に欠陥があるかどうかを教えてください、私はそれがベン図を考えるのに役立つことを発見しました。

これは、(私の場合は)提示されたオプションの中で最良の結果を出すようにしました。これはあまり複雑ではありませんでした。

SELECT * 
FROM A 
INNER JOIN B ON A.AId = B.AId 
WHERE A.ADate BETWEEN @Start and @End 
    and B.BDate NOT BETWEEN @Start and @End 

UNION ALL 

SELECT * 
FROM A 
INNER JOIN B ON A.AId = B.AId 
WHERE B.BDate BETWEEN @Start and @End 

は、おそらくこれは別の、大きなテーブルを照会する場合は特に、それは、日付範囲で動作しますが、私は想像し、他の述部で働くことができ、いくつかのシナリオでORオペレータのためのクエリの最適化である可能性があります。

+0

それはロジックを変更しないでしょうか? – Kekoa

+0

@Kekoaどのようにロジックが変更されていますか? –

+0

私は少し論理を変えました - (クリス私の前のフィルタリングは、彼が欲しくないANDのようなものでした)。今私は連合もやっていますが、私たちがフィルタリングするまで全行を検索しません。組合全体よりも速くてもよいでしょう。 –

関連する問題