MySQL查询优化之外连接优化

原文地址:https://dev.mysql.com/doc/refman/5.7/en/outer-join-optimization.html

译文:

8.2.1.8 外连接优化

外连接包括左连接和右连接。

MySQL按照如下形式实现连接条件A left join B:

    1)表B被设置为依赖于表A和A所依赖的所有表;

    2)表A被设置为依赖于左连接条件中使用的所有表(除了表B);

    3)左连接条件用于决定如何检索表B中的行(换句话说就是,任何where子句中的条件都不会被使用);

    4)所有标准的连接优化都会被执行,除非有一个表总是在它所依赖的所有表之后读取。如果存在循环依赖项,则会发生错误;

    5)所有标准的where优化都会被执行;

    6)如果表A中有一行跟where子句匹配,但是表B中没有与on条件匹配的行,表B中会额外产生一个所有值均为null的行与表A中的对应行匹配;

    7)如果你使用左连接区查询在一些表中不存在的行,并且在where条件中有col_name is null,其中col_name是声明为not null类型的列,当MySQL找到匹配left join条件的一行后,它会停止搜索更多的行(针对特定的组合键)。

右连接实现与左连接实现类似,只是表角色颠倒了。关于右连接如何被转化成等价的左连接,可以参考Section 8.2.1.9, “Outer Join Simplification”

对于一个左连接来说,如果生成的空行对应的where条件总是False,则左连接将变为为内连接。例如,在下面的查询中,如果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;

现在优化器可以在表t1之前使用表t2,如果这样做会产生更好的查询计划的话。要提供有关表连接顺序的提示,可以使用STARTING_JOIN,相关信息可以参考 Section 13.2.9, “SELECT Syntax”。但是,STARTING_JOIN可能会阻止索引的使用,因为它禁用了半连接转换,相关信息可以参考Section 8.2.2.1, “Optimizing Subqueries, Derived Tables, and View References with Semi-Join Transformations”

PS:由于水平有限,译文中难免存在谬误,欢迎批评指正。

猜你喜欢

转载自blog.csdn.net/qq_41080850/article/details/85270323