結合ヒントを追加すると、SQL Serverの行の見積もりが変更されるのはなぜですか?


15

私はいくつかのテーブルを結合し、かなり悪いパフォーマンスを発揮するクエリを持っています-行の推定はかなり(1000回)オフであり、ネストされたループ結合が選択され、複数のテーブルスキャンが発生します。クエリの形状は非常に単純で、次のようになります。

SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id 
WHERE t4.id = some_GUID

クエリをいじると、結合の1つにMerge結合を使用するようにヒントを出すと、実行が何倍も速くなることに気付きました。これは理解できます-結合結合は、結合されるデータにとってより良いオプションですが、SQL Serverはネストされたループを選択するだけでは正しく推定しません。

私が完全に理解していないのは、この結合ヒントがすべてのプラン演算子のすべての推定値を変更する理由です。さまざまな記事や本を読んで、計画を構築する前にカーディナリティの推定が実行されると想定したため、ヒントを使用しても推定は変更されず、SQL Serverに特定の物理結合実装を使用するよう明示的に指示します。

ただし、Mergeヒントを使用すると、すべての推定がほぼ完璧になります。なぜこれが起こるのか、ヒントなしでクエリオプティマイザーがより良い推定を行う一般的な手法はありますか?統計が明らかにこれを許可していることを考慮して?

UPD:匿名化された実行計画はここにあります:https : //www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan ? dl = 0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl = 0

TF 3604、9202、9204を使用して両方のクエリで使用される統計情報を確認しましたが、これらは同じです。ただし、スキャン/シークされるインデックスはクエリによって異なります。

それに加えて、クエリを実行しようとしましたOPTION (FORCE ORDER)-マージ結合を使用するよりも速く実行され、すべての結合にHASH MATCHを選択します。


3
外部結合はあるが、where句でテーブルを使用していることに気づきましたか?
ジェームズZ

@JamesZ-はい、私はそれを知っています、しかし、私はそれで問題があるとは思いません。
アレクサンダーシェルミン

9
@AlexShまあ、それはあなたの外部結合を内部結合に変更するため、論理的/意味的な問題があります。
アーロンバートランド

回答:


21

さまざまな記事や本を読むことから、私は計画を立てる前にカーディナリティの推定が実行されると仮定しました。

ではない正確に。初期基数推定値は、オプティマイザによって選択された最初の結合順序に影響を与える、(単純化および他の作業の後に)導かれます。

ただし、その後の探索(コストベースの最適化中)では、多くの場合、新しいカーディナリティの推定値が計算されます。これらの後のCEは、多かれ少なかれ「正確」です。結果が過小評価されている場合、オプティマイザはより安価に見えるプランを選択する場合がありますが、実際にははるかに長く実行されます。

一般に、意味的に同一のサブツリーのカーディナリティー推定が同じ結果を生成するという保証はありません。結局のところ、これは統計プロセスであり、一部の操作は他の操作よりも深いCEサポートを持っています。

あなたの場合、別の要因があるように見えます-オプティマイザーはTopを導入(または移動)し、その下のサブツリーに行ゴールを設定します:

計画フラグメント

トレースフラグ4138(2008 R2以降)を有効にした場合、予想と一致する推定値が見つかるか、オプティマイザーがネストされたループを選択しなくなる可能性があります。

ただし、Mergeヒントを使用すると、すべての推定がほぼ完璧になります。

ここには運の要素があります。人々は、物理的に実行されると予想される順序で、クエリ、または少なくとも結合を記述する傾向があります。結合ヒントの使用にはimpliedが付属FORCE ORDERするため、結合順序がテキスト形式に一致するように修正され、カーディナリティの再推定につながる多くのオプティマイザー探索ルールがオフになります。

それに加えて、クエリを実行しようとしましたOPTION (FORCE ORDER)-マージ結合を使用するよりも速く実行され、すべての結合にHASH MATCHを選択します。

これは結合のヒントと同じですが、物理的な結合演算子の選択を制限しません。繰り返しますが、クエリの結合順序を論理的な方法で記述した場合、合理的な計画が得られる可能性が非常に高くなります。もちろん、この方法ではオプティマイザーの機能の多くを逃してしまい、より一般的な状況では最適な結果が得られない可能性があります。

FORCE ORDER結合の順序を単純に強制するよりも幅広い効果を持つ非常に強力なヒント(ディレクティブ)であるため、おそらくあまり頻繁に使用する必要はないでしょう。たとえば、オプティマイザが集計を移動したり、部分的な集計を導入したりするのを防ぎます。私は、非常に例外的な状況および真に熟練したチューナーによる場合を除いて、このヒントを使用しないことを非常に勧めます。

詳細な分析には、現在の時間よりも時間がかかり、データベースの統計のみのコピーにアクセスする必要があります。


-10

どこが左を否定するの
かオプティマイザーでそれを難し​​くするのはなぜですか?
3つ以上の結合では、オプティマイザーは、メモリを保護するため、防御的になり、ループ結合に入ります。
条件や条件もループ結合に入る傾向があります-毎回発生する確固たる証拠はありますか-いいえ-まだ現実
複数の結合を使用すると、可能な場合に条件を結合から結合に引き込みます

SELECT t1.id
  FROM t1
  JOIN t2 
        ON t1.id = t2.t1_id
  JOIN t3 
        ON t2.id = t3.t2_id
  JOIN t4 
        ON t3.t4_id = t4.id 
       AND t4.id = some_GUID 

またはさらに良い-これはあなたのヒントや力に会うか、打ち負かすに違いない

SELECT t1.id
  FROM t1
  JOIN t2 
        ON t1.id = t2.t1_id
  JOIN t3 
        ON t2.id = t3.t2_id
       AND t3.t4_id = some_GUID

ヒントの問題は、特定の状態のデータ用であることです。クリーンなクエリを作成し、オプティマイザーに任せてください。時々、正しいことをするためにより多くの統計を必要とするだけですが、その後はロックインします。

なぜ異なる見積もり。別の計画。オプティマイザーに格闘のチャンスを与えるクエリから始めます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.