mysql左驱动表_MySQL多表联表查询驱动表选择

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

1. 联表的类型

我们经常使用的多表连接类型有以下三类:

1) 左连接(left join)

2) 右连接(right join)

3) 内连接(inner join)

关于这三种连接的区别,笔者在这里就不多说了,不了解的小伙伴们可以查阅相关的资料。

下面针对这三种连接分别做测试。

2.实践

在这里小伙伴们自己要准备两张表,笔者这里准备的是app,app_ext 这两张表,笔者这两张表比较复杂,这里就不全部展示出来了,需要注意的是笔者这里的mysql版本是8.0的。

1) 左连接和右连接

执行 explain select a.id,a.name,b.grade from app a left join app_ext b on a.id = b.appid; 其中a.id 是主键并且是自增的,app_ext 中的appid 与app.id 是关联的。输出结果如下:

2ddcf4d9f0fe

left_join.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;

2ddcf4d9f0fe

right_join.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;

输出结果如下:

2ddcf4d9f0fe

right_join.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 = '剑仙缘';

2ddcf4d9f0fe

right_join.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 = '剑仙缘';

2ddcf4d9f0fe

explain.png

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

2ddcf4d9f0fe

表索引.png

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

2ddcf4d9f0fe

explain.png

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

mysql > explain select id,name from app where user_id = 1079;

2ddcf4d9f0fe

explain.png

我们发现此时mysql扫描的次数大大减少了,原因很简单,因为mysql利用了索引,所以无需全部扫描。

总结:对于内连接mysql会选择扫描次数比较少的作为驱动表。

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值