3つのテーブルを含む共通のデータベース結合状況があります。 1つのテーブルAは、id
という名前の主キーを持つメインテーブルです。テーブルBおよびCは、エントリおよびAの補助データを含み、それぞれはid
という名前の列を持ち、これはA. id
を指す外部キーです。今、A、B、Cからのすべてのデータを1つのクエリで欲しいとすれば、私は次のように書いています。Oracleで還元剤結合条件を追加すると、異なる計画が発生する
SELECT *
FROM A
INNER JOIN B
ON B.id = A.id
INNER JOIN C
ON C.id = A.id
もちろん完璧に動作します。
最近、私たちのDBAは次のように、これはOracleのでは非効率的である、とあなたが同様にCとBの間の結合条件をする必要があることを私たちに語った:
SELECT *
FROM A
INNER JOIN B
ON B.id = A.id
INNER JOIN C
ON C.id = A.id AND C.id = B.id
これは私には冗長に見えたので、当然私はdidnのここで信じていない。実際には、実行計画がひどい低速なクエリに実際に遭遇し、不足している結合条件を正確に追加することによって問題を修正することができました。私は両方のバージョンで説明した計画を実行しました。「冗長」なクエリ条件のないものは1,035のコストでしたが、「改善された」ものは389でした(カーディナリティとバイトにも大きな違いがありました)。どちらのクエリでも同じ結果が得られました。
誰もこの余分な条件が違いをもたらす理由を説明できますか?私にはCとBは関連していません。また、他の結合条件を取り除くと、それは同じように悪いことに注意してください - 両方ともそこにいる必要があります。
私はあなたに同意します。Gary:統計が不正確であるため、一般的に、冗長な情報は提供しないでください。 –
これは私にとって最も説得力のある答えです。なぜなら、それはOracleに若干の希望を戻すからです。 (だから、私は少し不公平に偏っている。)実際の説明かどうかは、誰でも答えるのが難しい。 – waxwing