Skip to main content

9.外连接优化

外连接包括 LEFT JOIN和 RIGHT JOIN

MySQL实现如下: A LEFT JOIN B join_specification

  • 表 B 设置为依赖于表 A 以及 A 所依赖的所有表。
  • 表 A 设置为依赖于 LEFT JOIN 条件中使用的所有表(B 除外)。
  • LEFT JOIN 条件用于决定如何从表 B 中检索行。(换句话说,不使用 WHERE 子句中的任何条件。)
  • 执行所有标准连接优化,但表总是在其依赖的所有表之后读取。 如果存在循环依赖,就会发生错误。
  • 执行所有标准 WHERE 优化。
  • 如果 A 中有一行与 WHERE 子句匹配,但 B 中没有行与 ON 条件匹配,则会生成额外的 B 行,并将所有列设置为 NULL。
  • 如果使用 LEFT JOIN 查找某些表中不存在的行,并且有以下测试:WHERE 部分中的 col_name IS NULL,其中 col_name 是声明为 NOT NULL 的列,则 MySQL 会停止搜索更多行(例如 特定的组合键)在找到与 LEFT JOIN 条件匹配的行后。

RIGHT JOIN 实现与 LEFT JOIN 类似,只是表角色相反。 右连接转换为等效的左连接。

对于 LEFT JOIN,如果生成的 NULL 行的 WHERE 条件始终为 false,则 LEFT JOIN 将更改为内连接。 例如,如果 t2.column1 为 NULL,则以下查询中的 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 始终为 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,如果会产生更好的查询计划的话。 要提供有关表连接顺序的提示,请使用优化器提示; 或者,使用 STRAIGHT_JOIN。 然而,STRAIGHT_JOIN 可能会阻止使用索引,因为它禁用了半连接转换。