web-dev-qa-db-ja.com

最初にフィルターしてから結合するか、最初に結合してからフィルターしますか?

それぞれ10億以上のレコードを持つ5つのテーブルを考えてみます。

クエリはそれらを結合する必要があります。そして、私は彼らの記録の10%未満が必要とされることを知っています。すべてに日付ディメンションがあり、必要なのは今月のデータのみであるとします。

何が速くなりますか:

1)単純なSELECTを使用します。すべてのテーブルを結合し、今月の各テーブルのディメンションをフィルター(WHERE)します。

2)5つの一時テーブルを作成し、各ソーステーブルを当月のレコードにフィルターします。ここでは、必要な列のみを選択して、これらの一時テーブルを結合することもできます。

追加の可能性:

3)現在の月/年相当のデータのみを持つ二次テーブルを維持します。これらのテーブルは、メインのテーブルに供給する同じETLによって維持されます。

2
Hikari

クエリを作成して確認します。
クエリオプティマイザは、多くの場合、早期にフィルタリングするのに十分スマートです。
SQLは論理的です-の場所では、最後に処理されることを意味しません。

明らかに、結合とフィルターのインデックスが必要です。

5つ以上の結合に到達すると、オプティマイザはしばしば防御的になり、ループ結合に入ります。
引用はありますか-いいえ。観察です。

5つ以上になると、条件が結合に引き込まれますcanオプティマイザを支援します。
引用はありますか-いいえ。観察です。

select * 
from tableA 
join tableB  
      on tableA.fkB = tableB.id 
     and tableA.date1 >= @date1start   
     and tableA.date1 <  @date1end 
join tableC  
      on tableA.fkC = tableC.id 
     and tableC.filter1 = 'do me early'  

一度に1つの結合を構築し、それが愚かになるときを確認します。
一度に1つの結合を最適化します。

あなたが具体化しようとしているなら、#tempにpkを置いてください。
あなたが最大の力を得ようとしていると思うところから始めます。

OR条件は/結合が最も問題であり、ループ結合につながることがよくあります。
これらは最初に実現する必要があります。

ハッシュ結合を強制することはできますが、それはうまくいかない滑りやすい斜面です。

奇妙なことに、すべてのテーブルに日付ディメンションがあります。通常、より静的なタイプのデータを持ついくつかのルックアップタイプのテーブルがあります。

テーブルからの出力が必要ない場合、where where mayプリフォームの方が適しています。

3
paparazzo