web-dev-qa-db-ja.com

結合ヒントを追加すると、SQL Serverの行推定値が変化するのはなぜですか?

いくつかのテーブルを結合し、パフォーマンスがかなり悪いクエリがあります。行の見積もりが(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つにマージ結合を使用するように指示すると、実行が何倍も速くなることに気付きました。これは私が理解できることです。結合するデータにはマージ結合の方が適していますが、SQL Serverはネストされたループを選択しても正しく推定しません。

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

しかし、私が理解しているのは、Mergeヒントを使用すると、すべての推定がかなり完全になることです。なぜこれが発生し、クエリオプティマイザがヒントなしでより適切な推定を行うための一般的なテクニックはありますか?統計が明らかにこれを考慮していることを考えると?

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

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

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

15

さまざまな記事や本を読むことから、計画が構築される前にカーディナリティの推定が行われると想定しました。

ではない正確に。 初期カーディナリティ推定が導出され(簡略化およびその他の作業の後で)、オプティマイザが選択した初期結合順序に影響します。

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

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

あなたの場合、別の要因があるようです-オプティマイザはトップを導入(または移動)し、その下のサブツリーに 行の目標 を設定します。

Plan fragment

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

しかし、私が理解しているのは、マージヒントによってすべての推定がかなり完全になることです

ここには運の要素があります。人々は、クエリ、または少なくとも結合を、物理的に実行されると期待する順序で書く傾向があります。結合ヒントの使用には暗黙の_FORCE ORDER_が付属しているため、結合順序がテキスト形式に一致するように修正され、カーディナリティの再推定につながる可能性のある多くのオプティマイザ探索ルールがオフになります。

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

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

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

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

21
Paul White 9