什么是驱动表和被驱动表?在进行join连接查询时,驱动表和被驱动表都是怎么定义的?
分别对left join、right join、join进行一个说明。
1.left join时,左表是驱动表,右表是被驱动表
2.right join时,右表时驱动表,左表是驱动表
3.join时,mysql会选择数据量比较小的表作为驱动表,大表作为被驱动表
mysql 联表查询的逻辑是什么?
MySQL进行联表查询时,会使用到一个算法, Nest Loop Join,它其实是通过驱动表的结果集作为外层循环基础数据,然后遍历该结果集中的数据,把它作为过滤条件传到被驱动表中进行数据查询
,然后把结果进行合并。假设再有第三张表加入join,就把前两张表Join的结果集作为循环基础数据,再次遍历数据集传到到第三张表中进行查询数据,以此类推,不断重复。
如果想象成Java代码里的for循环,那就会好理解很多。
小表驱动大表,a left join b.
for(A表140条){
for(B表20万条){
}
}
大表驱动小表:
for(B表20万条){
for(A表140条){
}
}
显而易见,当用大表驱动小表,要进行20万次的连接,而用小表驱动小表,只需要进行140多次的连接就可以了。
以此咱也可以判断,当AB两表数据量差别不大时,其实就无所谓选择谁作为驱动表了。
在使用join进行联表查询时,如何选择驱动表和被驱动表才是效率最高的?
我们在进行sql优化时,需要记住一点,那就是永远以小表驱动大表。
例如有A、B两张表,A是小表,B是大表。
当用left join进行查询时,应该把A表放在前面,就是这样, select * from A a left join B b on a.xxx = b.xxx2,此时A表就是驱动表,B表就是被驱动表。
咱们可以来个具体点的测试,假设A表有140多条数据,B表有20万条数据。
执行 sql:select * from A a left join B b on a.xxx = b.xxx2
执行耗时:7.5s
执行 sql:select * from B b left join A a on a.xxx = b.xxx2
执行耗时:19s
当然这边是都没加索引的,此时咱们就可以得出上面的结论,小表驱动大表的执行效率要远高于大表驱动小表。
那如果join的列是加了索引的呢?这时sql能用上索引吗?
其实在进行join联表查询时,驱动表有索引是不会使用到索引的,被驱动表有索引则会用到索引。
还是上面的两张表,在以小表A驱动大表B的情况下,咱给大表B的xxx2字段建立索引就可以了,因为这能极大减少NestedLoop的循环总次数,从而能大大的提高执行效率和速度。
反之是不需要给小表A的xxx字段添加索引的,因为用不到的索引会造成资源浪费,还有会给mysql增加负担。
所以这边我们可以得出结论:永远给被驱动表的join列添加索引。
我们可以借助EXPLAIN来分析某条sql语句驱动表是哪张表,因为EXPLAIN语句分析出来的第一行的表即是驱动表。
上图的驱动表就是book,它的语句是 explain select * from class right join book on class.card = book.card;
MySQL联表join查询的优化总结
1、小表驱动大表
2、只在被驱动表上建索引
3、尽可能减少join语句中的NestedLoop的循环总次数,也就是让驱动表尽量的小
3、优先优化NestedLoop的内层循环,也就是增加被驱动表的索引命中率
5、索引没法优化时,可以提高JoinBuffer的大小,可以在my.conf文件里修改设置
本文由《MySql教程网》原创,转载请注明出处!https://mysql360.com