MySQL 5.1 リファレンスマニュアル :: 6 最適化 :: 6.2 SELECTステートメントおよびその他のクエリの最適化 :: 6.2.11 外側Join 単純化
« 6.2.10 入れ子結合最適化

6.2.12 ORDER BY最適化 »
Section Navigation      [Toggle]
  • 6.2 SELECTステートメントおよびその他のクエリの最適化
  • 6.2.1 EXPLAINを使用して、クエリを最適化する
  • 6.2.2 クエリパフォーマンスの推定
  • 6.2.3 SELECTクエリの速度
  • 6.2.4 WHERE 節最適化
  • 6.2.5 Range 最適化
  • 6.2.6 インデックス結合最適化
  • 6.2.7 IS NULL最適化
  • 6.2.8 DISTINCT最適化
  • 6.2.9 LEFT JOINとRIGHT JOIN最適化
  • 6.2.10 入れ子結合最適化
  • 6.2.11 外側Join 単純化
  • 6.2.12 ORDER BY最適化
  • 6.2.13 GROUP BY最適化
  • 6.2.14 LIMITの最適化
  • 6.2.15 テーブルスキャンを避ける方法
  • 6.2.16 INSERTステートメントの速度
  • 6.2.17 UPDATEステートメントの速度
  • 6.2.18 DELETEステートメントの速度
  • 6.2.19 その他の最適化のヒント

6.2.11. 外側Join 単純化

クエリのFROM節内テーブル表現は多くの場合単純化されています。

パーサ段階で、右外側joinオペレーションを含むクエリは左joinオペレーションを含む等価のクエリに変換されます。一般的には、変換は以下のルールに従って実行されます。

(T1, ...) RIGHT JOIN (T2,...) ON P(T1,...,T2,...) =
(T2, ...) LEFT JOIN (T1,...) ON P(T1,...,T2,...)

T1 INNER JOIN T2 ON P(T1,T2)フォームの全ての内側join表現は T1,T2、P(T1,T2)結合されたWHERE条件によって置き換えられます。(あるいは、組み込まれたjoinのjoin条件が存在する場合は、それに置き換えられます)。

オプティマイザが外側joinオペレーションのjoinクエリ計画を評価する際、各オペレーション時、外側テーブルが内側テーブルより前にアクセスされます。そのようなプランは、入れ子ループスキーマによる外側joinオペレーションを含むクエリの実行のみ可能なため、オプティマイザ選択肢は制限されています。

例えば、以下のようなフォームのクエリがあるとします。

SELECT * T1 LEFT JOIN T2 ON P1(T1,T2)
  WHERE P(T1,T2) AND R(T2)

R(T2)がテーブルT2からマッチする行を大幅に狭めます。クエリをそのまま実行した場合、オプティマイザはT1より前にT2をアクセスする以外に選択肢が与えられず、非常に非効率的な実行プランになることがあります。

幸い、MySQL WHERE条件がnull-rejectedの場合、そのようなクエリを外側joinオペレーションを含まないクエリに変換します。もし外側join オペレーションがNULL-によって補われたオペレーションのために作成された行のFALSEまたはUNKNOWNに評価される場合は、null-rejectedと呼ばれます。

よって、この外側joinでは:

T1 LEFT JOIN T2 ON T1.A=T2.A

以下のような条件はnull-rejectedです:

T2.B IS NOT NULL,
T2.B > 3,
T2.C <= T1.C,
T2.B < 2 OR T2.C > 1

以下のような条件はnull-rejectedではありません:

T2.B IS NULL,
T1.B < 3 OR T2.B IS NOT NULL,
T1.B < 3 OR T2.B > 3

条件が外側joinオペレーションにとってnull-rejectedか否かを確認する一般的なルールは単純です。以下の場合、条件はnull-rejectedになります。

  • フォームがA IS NOT NULLで、Aが内側テーブルのどれかの属性である場合

  • UNKNOWNのアーギュメントの内1つがNULLで、且つUNKNOWNと評価する内側テーブルへのリファレンスを含む述語である場合

  • null-rejected条件をコンジャンクトとして含んでいる結合子の場合。

  • null-rejected条件のディスジャンクションの場合。

条件は1つクエリでの外側joinオペレーションでnull-rejectedとなり、他のクエリでnot null-rejected になりえます。以下のクエリでは:

SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A
                 LEFT JOIN T3 ON T3.B=T1.B
  WHERE T3.C > 0

WHERE条件は、2つ目の外側joinオペレーションではnull-rejectedであり、1つ目の外側joinオペレーションではnot null-rejected です。

もしWHERE条件がクエリの外側joinオペレーションでnull-rejected である場合、外側joinオペレーションは内側joinオペレーションに置き換えられます。

例えば、前のクエリは以下のクエリに置き換えられます。

SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A
                 INNER JOIN T3 ON T3.B=T1.B
  WHERE T3.C > 0

オリジナルクエリには、1つのアクセス順序T1,T2,T3と対応するプランをオプティマイザが評価します。クエリを置き換える場合は、T3,T1,T2アクセスシーケンスを追加で考慮します。

1つの外側joinオペレーションの変換は別のオペレーションの変換を引き起こす場合があります。よって、以下のクエリでは:

SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A
                 LEFT JOIN T3 ON T3.B=T2.B
  WHERE T3.C > 0

は最初にこのクエリに変換されます。

SELECT * FROM T1 LEFT JOIN T2 ON T2.A=T1.A
                 INNER JOIN T3 ON T3.B=T2.B
  WHERE T3.C > 0

それはこのクエリと等価です。

SELECT * FROM (T1 LEFT JOIN T2 ON T2.A=T1.A), T3
  WHERE T3.C > 0 AND T3.B=T2.B

条件がT3.B=T2.Bnull-rejected であることと、外側joinを含まないクエリを取得したため、残る外側joinオペレーションは内側joinに置き換えることができます。

SELECT * FROM (T1 INNER JOIN T2 ON T2.A=T1.A), T3
  WHERE T3.C > 0 AND T3.B=T2.B

時折、組み込まれた外側joinオペレーションを置き換えることができても、組み込まれた外側joinが変換できない場合があります。以下のクエリでは:

SELECT * FROM T1 LEFT JOIN
              (T2 LEFT JOIN T3 ON T3.B=T2.B)
              ON T2.A=T1.A
  WHERE T3.C > 0

は以下変換されます。

SELECT * FROM T1 LEFT JOIN
              (T2 INNER JOIN T3 ON T3.B=T2.B)
              ON T2.A=T1.A
  WHERE T3.C > 0,

それは組み込まれた外側joinオペレーションを含むフォームにのみ書き換えることができます。

SELECT * FROM T1 LEFT JOIN
              (T2,T3)
              ON (T2.A=T1.A AND T3.B=T2.B)
  WHERE T3.C > 0.

組み込まれた外側joinオペレーションをクエリに変換する場合、WHERE条件とともに組み込まれた外側joinのjoin条件を考慮しなければいけません。以下のクエリでは:

SELECT * FROM T1 LEFT JOIN
              (T2 LEFT JOIN T3 ON T3.B=T2.B)
              ON T2.A=T1.A AND T3.C=T1.C
  WHERE T3.D > 0 OR T1.D > 0

WHERE は組み込まれた外側joinではnot null-rejected ですが、組み込まれた外側joinT2.A=T1.A AND T3.C=T1.Cのjoin条件はnull-rejectedになります。よって、クエリは以下に変換されます。

SELECT * FROM T1 LEFT JOIN
              (T2, T3)
              ON T2.A=T1.A AND T3.C=T1.C AND T3.B=T2.B
  WHERE T3.D > 0 OR T1.D > 0
Copyright © 1997, 2010, Oracle and/or its affiliates. All rights reserved. Legal Notices
Top / Previous / Next / Up / Table of Contents
© 2010, Oracle Corporation and/or its affiliates