mysql 查询3级分类表_MySQL多表联表查询驱动表选择

联表查询做开发的小伙伴会经常使用,但是可以大家都比较少去深入了解MySQL是怎么执行多表联表查询的,比如怎么选择驱动表(第一个被处理的表),是先联表还是说先根据where条件(前提是有where条件)进行过滤后在进行联表搜索符合条件的结果,等等。那这个里面可能涉及到的知识点比较多,就不仅仅是今天要讨论的驱动表的选择,还需要小伙伴们去了解更多相关的知识,比如:索引 ICP,nestedloop算法等等。后面笔者将更新相关的文章,供小伙伴们参考。

1. 联表的类型

我们经常使用的多表连接类型有以下三类:
1) 左连接(left join)
2) 右连接(right join)
3) 内连接(inner join)
关于这三种连接的区别,笔者在这里就不多说了,不了解的小伙伴们可以查阅相关的资料。
下面针对这三种连接分别做测试。

2.实践

在这里小伙伴们自己要准备两张表,笔者这里准备的是app,appext 这两张表,笔者这两张表比较复杂,这里就不全部展示出来了,需要注意的是笔者这里的mysql版本是8.0的。
1) 左连接和右连接
执行 explain select a.id,a.name,b.grade from app a left join appext b on a.id = b.appid; 其中a.id 是主键并且是自增的,appext 中的appid 与app.id 是关联的。输出结果如下:

74dff8f1e5ec13e2bc7c76b644e286c6.png

leftjoin.png

我们可以看到驱动表是我们的a表,下面我们改成right join 看下:
explain select a.id,a.name,b.grade from app a right join app
ext b on a.id = b.appid;

c59bcadd9ee59715792281af27be830d.png

rightjoin.png


可以看到mysql 选择了b表作为驱动表。
其实从上面的运行结果我们可以得出,左连接或者右连接的情况下是不管表中的记录数的,如果是左连接会选择左边的表作为驱动表,如果是右连接会选择右边的表作为驱动表。
2) 内连接
explain select a.id,a.name,b.grade from app a inner join app
ext b on a.id = b.appid;

输出结果如下:

c59bcadd9ee59715792281af27be830d.png

rightjoin.png


此时mysql 选择了b表作为了驱动表。下面我们再加些条件来看下运行结果:
explain select a.id,a.name,b.grade from app a inner join app
ext b on a.id = b.appid where a.name = '剑仙缘';

c59bcadd9ee59715792281af27be830d.png

rightjoin.png


我们看到mysql仍然是选择b表作为驱动表,我们再来单独分析下这条sql语句:
mysql > select count(id) from app where name = '剑仙缘';
+-----------+
| count(id) |
+-----------+
| 2 |
+-----------+
可以看到满足条件的记录实际上只有两行,下面使用explain 来看下这条语句的执行计划。
mysql > explain select id,name from app where name = '剑仙缘';

1200

explain.png

我们发现执行计划里面的rows仍然是需要扫描8137行数据,所以加上这个where条件并不能改变mysql所选择的驱动表。那如果where的条件是有索引的情况了,比如利用userid字段来检索,下图是笔者app数据表里面的索引:

d5cbbafd86b822b3e0bd292ff8e56ccb.png

表索引.png

mysql > explain select a.id,a.name,b.grade from app a inner join appext b on a.id = b.appid where a.userid= 1079;

c4195756dacd13efcb63c9140e9dff98.png

explain.png

我们发现此时mysql选择了a表作为了驱动表,我们再来单独分析下select id,name from app where userid = 1079;这条语句:
mysql > explain select id,name from app where user
id = 1079;

98e8f22de15bcfb5c7229ca3e180ecef.png

explain.png

我们发现此时mysql扫描的次数大大减少了,原因很简单,因为mysql利用了索引,所以无需全部扫描。总结:对于内连接mysql会选择扫描次数比较少的作为驱动表。

最后一点:我们从上面的测试结果中可以看出:当查询语句里面的where条件涉及到索引时,mysql会事先根据索引去过滤到一部分不符合条件的数据,然后再去和另外一张表的数据做匹配,反之,则会对全表进行扫描,等把所有的记录都查询出来再做过滤,这其实也是mysql内部做的一个优化-索引ICP,笔者将在后面的文章里面做详细的介绍。

好了,本篇文章就介绍到这里了,有不对的地方,欢迎小伙伴们指出,看到会及时回复的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值