Documentation Home

8.2.1.9 外连接优化

外连接包括LEFT JOINRIGHT JOIN

MySQL 实现如下: A LEFT JOIN B join_specification

  • B被设置为依赖于表A和依赖于它的所有表 A

  • A设置为依赖于条件B中使用的所有表(除了 )LEFT JOIN

  • LEFT JOIN条件用于决定如何从表中检索 行B。(换句话说,WHERE不使用子句中的任何条件。)

  • 执行所有标准连接优化,但始终在读取它所依赖的所有表之后读取表除外。如果存在循环依赖,则会发生错误。

  • 执行所有标准WHERE优化。

  • 如果其中有与子句A匹配的行WHERE,但没有与条件B匹配的 行,则会生成ON一个额外的 行,并将所有列设置为。 BNULL

  • 如果你LEFT JOIN用来查找某个表中不存在的行,并且你有以下测试:col_name IS NULLWHERE部分中,where col_name是一个声明为的列NOT NULL,MySQL 在找到后停止搜索更多行(对于特定的键组合)符合LEFT JOIN条件 的一行。

RIGHT JOIN实现类似于LEFT JOIN表角色颠倒 的实现。右连接转换为等效的左连接,如第 8.2.1.10 节“外部连接简化”中所述。

对于 a LEFT JOIN,如果 生成的行的WHERE条件始终为假,则将更改为内部联接。例如,如果是,则该 子句 在以下查询中将为假: NULLLEFT JOINWHEREt2.column1NULL

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 始终为假,因此变得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

现在优化器可以在表t2之前使用表,t1如果这样做会产生更好的查询计划。要提供有关表连接顺序的提示,请使用优化器提示;参见 第 8.9.3 节,“优化器提示”。或者,使用 STRAIGHT_JOIN; 参见 第 13.2.10 节,“SELECT 语句”。但是, STRAIGHT_JOIN可能会阻止使用索引,因为它会禁用半连接转换;参见 第 8.2.2.1 节,“使用半连接转换优化 IN 和 EXISTS 子查询谓词”