Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

10.2.1.9 外连接优化

外连接包括 LEFT JOINRIGHT JOIN

MySQL 实现了以下形式的 A LEFT JOIN B join_specification

  • B 依赖于表 A 及其所有依赖表。

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

  • 使用 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 相似,只是表角色被交换。右连接被转换为等效的左连接,如 第 10.2.1.10 节,“外连接简化” 中所述。

对于 LEFT JOIN,如果生成的 NULL 行的 WHERE 条件总是 false,则将 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 条件,而不是在后续优化阶段,这样可以使优化器将外连接转换为内连接;这可以改进包含琐碎条件的外连接查询计划,例如以下查询:

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

现在优化器可以在查询计划中使用表 t2 在表 t1 之前,如果这样做可以生成更好的查询计划。要提供关于表连接顺序的提示,请使用优化器提示;见 第 10.9.3 节,“优化器提示”。或者,使用 STRAIGHT_JOIN;见 第 15.2.13 节,“SELECT 语句”。然而,STRAIGHT_JOIN 可能会阻止索引的使用,因为它禁用了半连接变换;见 使用半连接变换优化 IN 和 EXISTS 子查询谓词