Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


10.2.1.9 外连接优化

外连接包括 LEFT JOINRIGHT JOIN

MySQL 实现了一个 A LEFT JOIN B join_ specification 如下所示:

  • B 被设置为依赖于表 A,以及所有表格,它们依赖于 A

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

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

  • 所有标准连接优化都将执行,除了表格总是读取它依赖于的所有表格之外。如果存在循环依赖关系,则会发生错误。

  • 所有标准 WHERE 优化都将执行。

  • 如果在 A 中有一个匹配 WHERE 子句的行,但是在 B 中没有匹配 ON 条件的行,则会生成一个额外的 B 行,其中所有列都设置为 NULL

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

RIGHT JOIN 实现与 LEFT JOIN 相似,只是表格角色相反。右连接转换为等效的左连接,如第 10.2.1.10 节所述,“外连接简化”。

对于一个 LEFT JOIN,如果 WHERE 条件始终对生成的 NULL 行为假,则 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;

在准备阶段移除的常量文字表达式的简单 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。为了提供关于表连接顺序的提示,请使用优化器提示;见第 10.9.3 节,“优化器提示”。或者,您可以使用 STRAIGHT_JOIN;见第 15.2.13 节,“SELECT 语句”。然而,STRAIGHT_JOIN 可能会阻止索引的使用,因为它禁用了半连接转换;见 Optimizing IN and EXISTS Subquery Predicates with Semijoin Transformations