数据库
首页 > 数据库> > MySQL多表联查底层执行原理

MySQL多表联查底层执行原理

作者:互联网

驱动表:
基表,就是Mysql先加载到内存中的那张表的数据,然后拿着这条数据去和其他表数据逐个比对。
被驱动表:
多表查询中除了基表,其他表都叫被驱动表。

驱动表的选择
在左(右)连接中,驱动表是由我们自己选择的,选择驱动表后,看where字句有没有驱动表的查询条件,有查询条件,则根据查询条件选出第一条符合条件的数据,然后拿这个数据,跟第一个被驱动表做关联查询,查询出来后,再看where字句有没有第一个被驱动表的查询条件,符合条件的留下,然后拿这条数据去查询第二个被驱动表,查询出来on的数据后,再看where 条件,以此类推。中间有一个不满足where条件的,就扔掉,查询下一条数据。这种方式叫做嵌套循环连接。即基表的每条数据,会跟每个被驱动表比对完后,再进行下一条数据的比对,而不是先是两表所有的数据查询完后,再和第三张表比对。
基表根据on条件查询被驱动表时,on条件有索引肯定查询被驱动表的数据效率就快,这就是为何提倡关联字段都加索引的原因。通过on条件查询出数据后,再根据where条件和select需要的字段,判断是否需要进行回表,还是通过索引就能满足条件,这就和单表查询是一样的了。

内连接查询
内连接查询的过程和上面叙述的过程是一样的,唯一不同的是,内连接查询,是由Mysql自己来决定用谁做基表的。Mysql中有很多算法,来根据不同的情况,选择不同的表作为基表。原则是把结果集最小的那张表,作为基表,来查询其他表。但是也会考虑其他表的索引情况,回表情况等综合因素,最终确定谁是基表,谁是被驱动表查询性能最高。具体的算法介绍可参考Mysql多表连接查询的执行细节

下面摘抄一段关于内连接的知识:

是否应该使用join连接查询?

对于多表间查询,可以使用join关联,也可以拆成多张表的单独查询。对于join关联查询,如果使用不当,很容易造成对被驱动表的多次扫描(Block Nested-Loop join),进而导致IO压力增大,同时多次的扫面被驱动表,会导致被驱动表的数据页被置入mysql buffer-pool的young区域,一次join就替换掉之前真正的热点数据页。

正常一次查询仅全表扫描一次数据的话,数据页会被放入buffer pool的old区域的前端,但是如果一个数据页在第一次使用时,如果不在buffer pool,那么会加载仅buffer pool,放在old区域的前端,但是如果这个数据页在buffer pool,且距离上次使用时间超过1S,也就是join查询时间拆过1S,那么就会把数据页放到buffer pool的young区域,也就是热点区域,这样会导致原先真正的热点数据被替换。这样即使join查询结束了,对mysql的性能有很直接的负面影响,也就是buffer pool内存命中率突然暴跌,查询时间突然变长,很多都需要读取磁盘,需要很长时间才能恢复。

所以,对于大表的关联查询,如果没有使用上索引,也就是on的字段没有索引,通过explain能看到Extra里有Using join buffer(Block Nested Loop),那么就不要使用join了。当然能使用上使用的join查询还是比单表查询来的快的,同时还能很方便的做结果筛选。

关于Buffer Pool的Young区和Old区,以及其LRU算法机制,以后单独进行研究

标签:多表,join,基表,buffer,查询,MySQL,驱动,联查,数据
来源: https://blog.csdn.net/qq1309664161/article/details/122873951