MySQL的Join到底能不能用
经常听到2种观点:
其实对于上面的观点一定程度上是正确的,但不是完全正确。但之所以流传这么广,主要还是没有搞清楚实际状态,而根据实际使用中总结出来的一些模糊规律。只有了解的MySQL的Join实际执行方式,就会知道上面2种观点是一种模糊的规律,这种规律并不能指导我们实际开发。下面就说说MySQL的实际join执行方式。
MySQL的Join是如何执行的
join可以说一种集合的运算,比如left join,right join,inner join,full join,outer join,cross join等,这些集合间的计算关系对应在高中数学集合里面的交集,并集,补集,全集等。但在实际的代码中,join运算基本上是通过多层循环来实现的。
举一个例子,假设有t1,t2两张表,表结构分别如下:
createtablet1( idintnotnullAUTO_INCREMENT, usernamevarchar(20)notnulldefault'', ageintnotnulldefault0, PRIMARYkey(`id`) )ENGINE=INNODBDEFAULTCHARSET=UTF8MB4; createtablet2( idintnotnullauto_increment, usernamevarchar(20)notnulldefault'', scoreintnotnulldefalut0, primarykey(`id`) ))ENGINE=INNODBDEFAULTCHARSET=UTF8MB4;
假设t1有100条数据,t2表有200条数
查询sql为:
selectt1.*,t2.*fromt1leftjoint2on(t1.username=t2.username)
那么这条SQL的执行步骤如下:
基本上先遍历t,1,然后根据t1中的每行数据中的username,去表t2中查找满足条件的记录。基本就是2层循环。
如何优化join查询
从上面可以看出,join本质是循环,这里的开销如下:
从上面的步骤可以看出,优化方向:
优化的基本方法:
Batched Key Access Join 这个是 Index Nested Join上做的优化,因为回表的存在,随机操作io也很耗费性能,这个算法的核心在于通过辅助索引去查找时,将得到的主键进行排序,然后按照主键递增的顺序进行查找,对磁盘的读接近顺序读,从而优化性能
到底要不用Join
从上面的分析我们可以看到,用Join还是可行的,只要性能可控且在接受范围内,还是能减少代码复杂度的。需要避免的是join的表没有索引,不然这样的SQL发线上是灾难性的。
Join还是可以大胆的使用,只要把握好几个原则: