sql left join 多表连接
mysql的leftjoin和innerjoin的效率对⽐,以及如何优化
⼀、前⾔
最近在写代码的时候,遇到了需要多表连接的⼀个问题,初始sql类似于:
select * from a left join b on a.x = b.x left join c on c.y = b.y left join d on d.z=c.z
这样的多个left join组合,⼀⽅⾯是⼼⾥有点不舒服,总觉得这种写法是有问题的,⼀⽅⾯有有点好奇,直接⽤inner join会怎样呢?差别在哪⾥?后续使⽤inner join发现速度要⽐left join快⼀些,所以这边就研究⼀下这个问题。
⼆、left join为什么会⽐ inner join 慢
1、关于逻辑运算量
关于left join的概念,⼤家是都知道的(返回左边全部记录,右表不满⾜匹配条件的记录对应⾏返回null),那么单纯的对⽐逻辑运算量的话,inner join 是只需要返回两个表的交集部分,left join多返回了⼀部分左表没有返回的数据。
2、关于mysql连接的算法 Nest Loop Join(嵌套联接循环)
这个算法是mysql默认的连接算法,类似于我们php程序的三个嵌套循环:
(foreach a as v){
(foreach b as v1){
(foreach c as v2){
}
}
}
从算法上来看,根据mysql⽂档,inner join在连接的时候,mysql会⾃动选择较⼩的表来作为驱动表,从⽽达到减少循环次数的⽬的。我们在使⽤left join表的时候,默认是使⽤左表作为驱动表,那么此时左表的⼤⼩是我们来控制的,如果控制不当,左表⽐较⼤,那么⾃然循环次数也会变多,效率会下降。
根据这两⽅⾯的对⽐,left join明显被秒成渣,但是我们的实际业务却经常需要使⽤left join,⼀切还是
要以实际业务为主,所以⼤家还是仁者见仁智者见智的选择吧。博主这⾥因为业务并不是很需要left join,所以果断选择使⽤inner join来连接表。
三、关于 left join的优化
根据上⾯咱们的对⽐,基本可以总结出来⼀些简单的优化⽅案。
1、left join选择⼩表作为驱动表(这部分基本是⼤家的共识)
2、如果左表⽐较⼤,并且业务要求驱动表必须是左表,那么我们可以通过where条件语句,使得左表被过滤的⼩⼀些,主要原理和第⼀条类似
3、关联字段给索引,因为在mysql的嵌套循环算法中,是通过关联字段进⾏关联,并查询的,所以给关联字段索引很必要
4、如果sql⾥⾯有排序,请给排序字段加上索引,不然会造成排序使⽤全表扫描
参考:www.oschina/question/930697_2190172
5、如果where条件中含有右表的⾮空条件(除开is null),则left join语句等同于join语句,可直接改写成join语句。
6、根据⽂档,MySQL能更⾼效地在声明具有相同类型和尺⼨的列上使⽤索引。所以把表与表之间的关联字段给上encoding和collation(决定字符⽐较的规则)全部改成统⼀的类型
7、右表的条件列⼀定要加上索引(主键、唯⼀索引、前缀索引等),最好能够使type达到range及以上(ref,eq_ref,const,system)
推荐博客阅读:
博主在查过各种资料之后,最终把⾃⼰的连接类型改为了inner join,并且给关联字段以及排序字段都加上了索引,速度⽐起刚开始的时候确实是快了不少。只是说mysql还有很多需要研究的地⽅,加油吧,碰到并解决,不亏~
end

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。