# 4.7 外部连接优化

外部连接包括`LEFT JOIN`和 `RIGHT JOIN`。

MySQL实现如下： `*`A`* LEFT JOIN *`B`* *`join\_specification`*`

* 表\*`B`*被设置为依赖于表*`A`\*以及所依赖的所有表 *`A`*。
* 表格\*`A`*被设置为取决于条件*`B`\*中使用的所有表格（除外）`LEFT JOIN`。
* 该`LEFT JOIN`条件用于确定如何从table中检索行 *`B`*。（换句话说，`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`表角色相反的实现。将右连接转换为等效的左连接。

对于`LEFT JOIN`，如果 `WHERE`条件对于生成的`NULL`行始终为false ，则将`LEFT JOIN`其更改为内部连接。例如， `WHERE`如果条款是在下面的查询错误的`t2.column1`是 `NULL`：

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

因此，将查询转换为内部连接是安全的：

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

现在，如果这样做会导致更好的查询计划，那么优化器可以先使用表，`t2`然后使用表`t1`。要提供有关表连接顺序的提示，请使用`STRAIGHT_JOIN`；。但是，`STRAIGHT_JOIN`由于它禁用了半连接转换，因此 可能会阻止使用索引。
