10.2.1.9 外连接优化
外连接包括 LEFT JOIN
和 RIGHT 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
来查找某些表中不存在的行,并且您有以下测试:
在 WHERE 部分,其中col_name
IS NULLcol_name
是一个声明为NOT NULL
的列,MySQL 将在找到匹配LEFT JOIN
条件的行后停止搜索更多行(对于特定的键组合)。
RIGHT JOIN
实现与 LEFT JOIN
相似,只是表格角色相反。右连接转换为等效的左连接,如第 10.2.1.10 节所述,“外连接简化”。
对于一个 LEFT JOIN
,如果 WHERE 条件始终对生成的 NULL
行为假,则 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 总是假,因此 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。