上記のクエリプランのいくつかを理解しようとしています。
グループ化されていない場合、クエリにStream Aggregateがあるのはなぜですか。結合がマージされ、ソートが行われることと関係があると思いますか?
第二に、より重要なのは、なぜ13の推定値が
ストリームに集約すると、24,595,900の見積もりが出ますか?これにより、ネストされたループの代わりにクラスター化インデックスがスキャンされるObject4の2番目の問題が発生します。 ORを使用する代わりに、クエリを2つのクエリに分割する必要があり、結合がネストされたループに変わり、Object4にシークしました。
クエリプラン
最初の質問に答えるには:
グループ化されていない場合、クエリにStream Aggregateがあるのはなぜですか。結合がマージされ、ソートが行われることと関係があると思いますか?
SQL Serverはクエリを効果的に書き換えています。このクエリ:
_select Object1.Column1
FROM Object2 Object3 WITH (ROWLOCK)
INNER JOIN Object4 Object1 WITH (ROWLOCK) ON Object3.Column2 = Object1.Column1
WHERE Object3.Column2 in (SELECT Column2 FROM Object5)
or Object3.Column3 in (SELECT Column2 FROM Object5);
_
次のように書くこともできます:
_select Object1.Column1
FROM
(
select Object3.Column2
FROM Object2 Object3 WITH (ROWLOCK)
WHERE Object3.Column2 in (SELECT Column2 FROM Object5)
UNION
select Object3.Column2
FROM Object2 Object3 WITH (ROWLOCK)
WHERE Object3.Column3 in (SELECT Column2 FROM Object5)
) Object3
INNER JOIN Object4 Object1 WITH (ROWLOCK) ON Object3.Column2 = Object1.Column1;
_
そのため、クエリプランの_Object2
_には2つの異なるアクセスメソッドがあります。 Merge Join (Concatenation)
操作は、実際にはマージ結合ではありません。 _UNION ALL
_を実装して結果を組み合わせるだけです。あなたが_Object3.Column2
_でグループ化したストリーム集約。これは、Merge Join (Concatenation)
から重複を削除し、データをソートして、次の_MERGE JOIN
_からObject4で使用できるようにします。
2番目の質問に答えるには:
次に、さらに重要なのは、ストリームの集計に入る13の推定値が24,595,900の推定値として出るのはなぜですか。これにより、ネストされたループの代わりにObject4がクラスター化インデックスをスキャンするという2番目の問題が発生します。 ORを使用する代わりに、クエリを2つのクエリに分割する必要があり、結合がネストされたループになり、Object4にシークしました。
バグのようです。いくつか検索したところ、 Paul Whiteの記事 問題を説明していることがわかりました。バグに投票したい場合、または影響を受けたとして自分を追加したい場合、バグは Connect に報告されます。
要約すると、27328800(_Object2
_のテーブルカーディナリティ)* 0.9 =丸め後の24595900であるため、カーディナリティの推定値は24595900です。 SQL Server 2008を使用しているため、レガシーCE計算が使用されます。
2014年より前のカーディナリティエスティメータでも同様の問題が発生しますが、最終推定は代わりに推定セミジョイン入力の90%に固定されます(逆に固定された10%述語推定に関連する面白い理由のため、転換が多すぎて取得できません)に)。
記事全体を読むことをお勧めします。問題を要約するのは少し難しいですが、最後の方にあるテキストの一部を引用することでそうしようと思います。
カーディナリティエスティメータは、100%の選択性で固定結合計算機を使用します。その結果、準結合の推定出力カーディナリティはその入力と同じになります。つまり、履歴テーブルのすべての113443行が対象となることが期待されます。
バグの正確な性質は、セミジョインの選択性の計算で、入力ツリー内のすべてのユニオンを超えて配置された述語がすべて失われることです。以下の図では、準結合自体に述語がないことは、すべての行が適格であることを意味します。連結より下の述語(union all)の影響は無視されます。
2014年より前のカーディナリティエスティメータでも同様の問題が発生しますが、最終推定は代わりに推定セミジョイン入力の90%に固定されます(逆に固定された10%述語推定に関連する面白い理由のため、転換が多すぎて取得できません)に)。
以前と同じようにクエリを分割すると、問題を回避できます。また、UNION
を使用してクエリを書き直すこともできます(記事の例4を参照)。