#### 8.2.1.9 外连接优化

[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)

外连接包括`左连接`和`正确加入`.

MySQL 实现了一个`*`一种`* 左连接 *`乙`* *`加入规范`*`如下：

-   桌子*`乙`*设置为依赖表*`一种`*和所有的桌子*`一种`*要看。

-   桌子*`一种`*设置为依赖于所有表（除了*`乙`*) 中使用的`左连接`健康）状况。

-   这`左连接`条件用于决定如何从表中检索行*`乙`*.（换句话说，任何条件`在哪里`不使用子句。）

-   执行所有标准连接优化，除了一个表总是在它所依赖的所有表之后被读取。如果存在循环依赖，则会发生错误。

-   所有标准`在哪里`执行优化。

-   如果有一行*`一种`*匹配的`在哪里`子句，但没有行*`乙`*匹配的`在`条件，额外*`乙`*生成行，所有列设置为`空值`.

-   如果你使用`左连接`查找某些表中不存在的行，并且您有以下测试：`*`col_name`* 一片空白`在里面`在哪里`部分，在哪里*`col_name`*是一个声明为的列`非空`, MySQL 在找到与`左连接`健康）状况。

    这`正确加入`实现类似于`左连接`与表角色颠倒。右连接被转换为等效的左连接，如中所述[第 8.2.1.10 节，“外部连接简化”](outer-join-simplification.html).

    为一个`左连接`，如果`在哪里`生成的条件始终为假`空值`行`左连接`改为内连接。例如，`在哪里`如果以下查询中的子句为假`t2.column1`是`空值`：


```
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 及更高版本中，微不足道`在哪里`常量文字表达式产生的条件在准备过程中被删除，而不是在优化的后期阶段，此时连接已经被简化。提前去除琐碎条件允许优化器将外连接转换为内连接；这可能会导致改进的查询计划在外部连接中包含琐碎的条件`在哪里`子句，例如这个：

```
SELECT * FROM t1 LEFT JOIN t2 ON condition_1 WHERE condition_2 OR 0 = 1
```

优化器现在在准备过程中看到 0 = 1 总是错误的，使得`或 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 节，“优化器提示”](optimizer-hints.html).或者，使用`STRAIGHT_JOIN`;看[第 13.2.10 节，“SELECT 语句”](select.html).然而，`STRAIGHT_JOIN`可能会阻止使用索引，因为它禁用了半连接转换；看[第 8.2.2.1 节，“使用半连接转换优化 IN 和 EXISTS 子查询谓词”](semijoins.html).
