MySQL 8.0 リファレンスマニュアル


8.2.1.9 外部結合の最適化

外部結合には、LEFT JOIN および RIGHT JOIN が含まれます。

MySQL は、次のように A LEFT JOIN B join_specification を実装します:

  • テーブル B は、テーブル AA が依存するすべてのテーブルに依存して設定されます。

  • テーブル A は、LEFT JOIN 条件で使用されるすべてのテーブル (B を除く) に依存して設定されます。

  • LEFT JOIN 条件は、テーブル B からの行の取得方法を決定するために使用されます。 (言い換えると、WHERE 句内のすべての条件が使用されません)。

  • テーブルは常にそれが依存するすべてのテーブルのあとに読み取られることを除き、すべての標準の結合最適化が実行されます。 循環依存関係がある場合は、エラーが発生します。

  • すべての標準 WHERE 最適化が実行されます。

  • AWHERE 句に一致する行があるが、BON 条件に一致する行がない場合、すべてのカラムが NULL に設定された追加の B 行が生成されます。

  • LEFT JOIN を使用して、一部のテーブルに存在しない行を検索し、WHERE 部分の col_name IS NULL のテストを実行した場合 (ここで col_nameNOT NULL と宣言されているカラム)、MySQL は LEFT JOIN 条件に一致する 1 つの行が見つかったあとに、それ以上の行 (の特定のキーの組み合わせ) の検索を停止します。

RIGHT JOIN の実装は、テーブルロールを逆にした LEFT JOIN の実装に似ています。 セクション8.2.1.10「外部結合の単純化」 で説明されているように、右結合は同等の左結合に変換されます。

LEFT JOIN では、生成された NULL 行の WHERE 条件が常に false の場合、LEFT JOIN は内部結合に変更されます。 たとえば、t2.column1NULL であった場合、次のクエリーの WHERE 句は false になります。

SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2=5;

したがって、クエリーを内部結合に変換しても安全です:

SELECT * FROM t1, t2 WHERE t2.column2=5 AND t1.column1=t2.column1;

MySQL 8.0.14 以降では、定数リテラル式から発生する簡単な WHERE 条件は、最適化の後の段階ではなく、準備中に削除され、結合がすでに簡略化されています。 以前に簡易条件を削除すると、オプティマイザは外部結合を内部結合に変換できます。これにより、次のような WHERE 句に簡易条件を含む外部結合を含むクエリーの計画が改善される可能性があります:

SELECT * FROM t1 LEFT JOIN t2 ON condition_1 WHERE condition_2 OR 0 = 1

オプティマイザは、準備中に 0 = 1 が常に false であることを確認し、OR 0 = 1 を冗長にして削除し、次の状態のままにします:

SELECT * FROM t1 LEFT JOIN t2 ON condition_1 where condition_2

これで、オプティマイザは、次のようにクエリーを内部結合としてリライトできます:

SELECT * FROM t1 JOIN t2 WHERE condition_1 AND condition_2

これによりクエリー計画が改善される場合、オプティマイザはテーブル t1 の前にテーブル t2 を使用できるようになりました。 テーブルの結合順序に関するヒントを提供するには、オプティマイザヒントを使用します。セクション8.9.3「オプティマイザヒント」 を参照してください。 または、STRAIGHT_JOIN を使用します。セクション13.2.10「SELECT ステートメント」 を参照してください。 ただし、STRAIGHT_JOIN では準結合変換が無効になるため、インデックスの使用が妨げられる場合があります。セクション8.2.2.1「準結合変換による IN および EXISTS サブクエリー述語の最適化」 を参照してください。


関連キーワード:  テーブル, 結合, インデックス, InnoDB, 外部, WHERE, クエリー, LEFT, ステートメント, 条件