Seeker-Wu的专栏

只有行动,才能证明你自己。

mysql5.7官网直译SQL语句优化--左右连接的优化

1.8Left Join and Right Join Optimization(左连接和右连接的优化):
mysql执行一个A left join B的连接条件如下:
>表B是一个依赖于A和A依赖的所有其他表共同决定的集合。
>表A是一个依赖于用于left join条件的除B表意外的所有表的一个集合。
>LEFT JOIN条件被用来决定怎么样检索B表中的行。(换句话说,任何在where中的查询条件都不用)
>所有的标准连接优化都会被执行,除非一个表一直被它依赖的全部表读取。如果查询中有环形依赖,则会报错。
>所有标准的WHERE优化会被执行。
>如果A中有一行能够满足where条件,但是B中没有行满足ON条件。则一个额外的行在B中生成用于连接,其中的值都是NULL。
>如果你使用LEFT JOIN去查找在一些表中不存在的行数据,而且你有查询条件:col_name is NULL 在where 查询部分,而且col_name 是一个被声明为NOT NULL的列,mysql会停止查找更多的行(对于一个特别的key组合),当他找到一行与左连接条件匹配的行时。
右连接的实现和左连接类似,只是表角色互换。右连接可以转换为等价的左连接,具体描述请看8.2.1.9的外链接的简单化。
连接优化器按照顺序计算连接中用到的表。被LEFT JOIN左连接或者STRAIGHT_JOIN直连接强制确定读取的表顺序帮助连接优化器更快的完成它的工作,因为只有很少的表需要排列去检查。这也意味着如果你执行一个查询按照如下的形式,那么mysql会完成一个在b表的全表扫描,因为LEFT JOIN会强制在读取d之前执行:
SELECT *
  FROM a JOIN b LEFT JOIN c ON (c.key=a.key)
  LEFT JOIN d ON (d.key=a.key)
  WHERE b.key=d.key;


修复这种情况通过修改a和b在from 中的顺序:
SELECT *
  FROM b JOIN a LEFT JOIN c ON (c.key=a.key)
  LEFT JOIN d ON (d.key=a.key)
  WHERE b.key=d.key;


对于一个左连接,如果where条件总是false也就是对于生成的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;
现在优化器能够在在表t1之前使用表2,如果这样执行将会形成一个更好的执行计划。为了提供一个表连接顺序的提示,使用直连接(STRAIGHT_JOIN);具体请看13.2.9的select语法。然而,直连接可能阻止被用于查询的索引。因为它不支持semi-join的转变;具体请看8.2.2.1的优化子查询,派生表,和试图引用通过Semi-join的转变。
到此左连接和右连接的优化就结束了,接下来我们要说的是1.9 Outer Join Simplifiation 外连接的简单化.
阅读更多
个人分类: 翻译 mysql
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭