Mysql left join和 join的区别
刚好实践中遇到一个left join 和 join的问题。
还原案发现场:
keyword表数据有3w多条
re表数据数百条
1.select k.* from keyword k join re r on k.id=r.cpc_id
where report_date = ‘2020-11-13’
这个sql很快就能查询出来
2.select k.* from keyword k left join re r on k.id=r.cpc_id
where report_date = ‘2020-11-13’
这个sql语句执行的时候,我们可以先泡个面。
分析思路:
首选想到的肯定是索引,因为mysql的优化查询手段最常用的就是加索引。
那么索引要怎么加呢?
由于k.id已经是主键索引,那肯定不用加。
那在r.cpc_id 加索引,由于还有report_date查询条件,所以加个联合索引
idx_cpcId_reportDate(cpc_id,report_date)
(ps:一次查询语句中,仅有一个索引能发挥作用,所以需要联合索引)
结果:
bingo。查询速度都优化了。由13秒变成0.7秒,这谁顶得住
索引优化前
索引优化后
我们用explain来看看sql语句的执行过程
(ps:system/const/eq_ref/ref/range/index/ALL 越靠后查询效率越低)
未加索引:
type=All,并且使用了临时表还有文件排序,查询效果最差的标志一下子都齐了。笛卡尔集是30750*1875
加索引:
这里其实还有优化空间,type=index还可以继续优化,但是我们明显看到临时表和文件排序都优化了,并且笛卡尔集是30750
剖析原因:
这是为什么呢???
加了索引后,就等于左表只需遍历右表索引高度,而不是整个右表的条数。所以性能大大提升
原理:
MySQL实现join的原理,原来MySQL内部采用了一种叫做 nested loop join的算法。Nested Loop Join 实际上就是通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与 Join,则再通过前两个表的 Join 结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据。如此往复。
并且left join是用大表来驱动小表,join是小表驱动大表。
所以即使不加索引,join的速度远远优于left join,再配合where条件也降低了好多个数量级。。。。。
那么如何优化left join:
1、尽量使用内连接
2、连表条件on中尽量能够过滤一些行将驱动表变得小一点,用小表去驱动大表
3、右表的条件列一定要加上索引(主键、唯一索引、前缀索引等),最好能够使type达到range及以上(ref,eq_ref,const,system)