3つの行を含む一時テーブル#terminがあります。
次のクエリを実行すると
_SELECT t.termin, ttw.tourid, twt.va_nummer_int
FROM #term AS t
INNER JOIN plinfo.t_touren_werbeflaechentermine AS ttw
ON ttw.termin = t.termin
INNER JOIN wtv.t_werbeflaechentermine AS twt
ON twt.jahr = t.jahr
AND twt.termin = t.termin
AND twt.ID_Wt = ttw.id_wt
GROUP BY t.termin, ttw.tourid, twt.va_nummer_int
_
各テーブルは、一致するインデックスを使用して結合されます。両方のテーブルは、ps_termin(termin)によって分割されます。
最初のテーブル(t_touren_werbeflaechentermine)の場合は、パーティションの削除を実行して行のサブセットのみを読み取り、2番目のテーブル(t_werbeflaechentermine)の場合は、インデックス全体をスキャンします(jahr, termin, id_wt include (va_nummer_int)
)。
だから私の質問:なぜそれはインデックススキャン(およびシークなし)であり、なぜそれは2番目のテーブルのパーティションを排除しません。
PS:2番目のテーブルでWITH (FORCESEEK)
を使用すると、実行プランの両方のテーブルが切り替えられ、最初のテーブルでフルインデックススキャンが実行されます...
PPS:実行計画を見つけることができます ここ
なぜインデックススキャンなのか?
SQL Serverは、ループシークアプローチと比較して、データのスキャンコストが低い(1.7 MM行のみなので、比較的小さいテーブルである)と推定している可能性があります。
_t_werbeflaechentermine
_テーブルをスキャンすると、すべての_1,708,658
_行が処理され、計画はこれが_7,347 logical reads
_を実行することを示しています。
ループシークは、_~70K seeks
_(ループの外側のカーディナリティの推定)を実行すると推定されます。シークがバイナリ検索であると想定すると、そのため、これは70109.4 * LOG(1708658,2)
、または_1,451,575
_の複雑さを持つと推定できます。
これは、スキャンによって処理される_1,708,658
_行よりわずかに低くなりますが、(推定)〜70Kシークのそれぞれが複数の論理読み取りを実行するため、論理読み取りの数ははるかに多くなり、より多くの論理読み取りが生成されます選択されたスキャン。これが、ループシークプランの推定コストが高くなり、選択されなかった理由かもしれません。
スキャンなしでプランを表示
このプランをループシークを使用する実行プランと比較する場合は、両方の結合でループシークを使用する場合は、クエリにOPTION (LOOP JOIN)
クエリヒントを追加して、両方の結合でループ結合が使用されるようにします。 。比較のために、この実際の実行計画を投稿することは有益です。
なぜパーティションが削除されないのですか?
SQL Serverには、ハッシュ結合のビルド側で観察されたパーティションに基づいてパーティションの除去を実行するハッシュ結合アルゴリズムがないため、_t_werbeflaechentermine
_のパーティションの除去は発生しないと思います。これは場合によっては最適な最適化になりますが、私の知る限り、現在のオプティマイザでは使用できません。パーティションの削除は、ループ結合の内側では使用できますが、ハッシュ結合のプローブ側では使用できません(クエリにパーティション列の明示的な述語)。
さらに読むために、SQL Serverには連結結合の概念があります。この結合では、ハッシュ結合は、同じ方法でパーティション化された2つのテーブルの各パーティションに個別に適用されます。ただし、この最適化は双方向結合でのみ使用できるため、クエリは対象外です。 Paul Whiteは、これと他のパーティションテーブル結合の考慮事項について パーティションテーブル結合パフォーマンスの向上 でより詳細に説明しています。