细谈left join和join

csdntup

👏作者简介:大家好,我是爱发博客的嗯哼,爱好Java的小菜鸟
🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
📝社区论坛:希望大家能加入社区共同进步
🧑‍💼个人博客:智慧笔记
📕系列专栏:

前言

相信大家都知道在MySQL中的join、left join和right join,在业务中,需要两表联查总会用到联合查询语句。但大家却有可能并不太了解他们底层是如何进行处理的,也就无法在业务量大的情况下,去优化这些sql语句。

本节我就为大家通过执行流程层面进行一些讲解,相信大家看完本篇文章对以后的优化处理也就不会毫无头绪了。

MySQL整体架构

如果大家对于MySQL架构一点都不了解,可以去看一下这篇MySQL基本架构

在了解一种技术之前,最主要的就是知道其底层架构。只有知道了底层架构,才能在后续的基础上更轻松的掌握整体。

在这里插入图片描述

MySQL主要分为两个层面,一个是Server层,即MySQL官方自己的核心层面。另一个就是存储引擎层,这个相当于一个插件,所有人都可以基于MySQL官方给的结构进行实现存储引擎。

而要谈论的核心就是存储引擎层。使用不同的存储引擎,优化的方式也就不一样。而我们要谈论的是当前官方默认的存储引擎—InnoDB存储引擎

这张就是innodb的缓冲池,而和join优化相关的缓冲就是最不起眼的那个—额外的缓冲池

相信大家都知道缓冲池的功能,这里就不再过多赘述了。

join和left join执行流程

在join类型语句执行时一般会有两个表,一个为驱动表,另一个为被驱动表。首先执行引擎会去磁盘找到驱动表第一行数据,再去磁盘找到跟第一行匹配的语句。直到找完驱动表对应的所有匹配数据。

大家或许有疑问了,驱动表有什么好处呢?

这就用到上面的缓冲池这个东西了,执行引擎会将驱动表取出来放入缓冲池中,在内存遍历一行行数据去磁盘匹配对应的被驱动表数据。内存的速度是磁盘的几百倍,这样的话会比两表都在磁盘遍历快上很多倍。

有一个表有索引

既然大家知道了join过程会使用缓冲池,那当一个表有索引的时候,应该选哪个表作为驱动表合适?

首先驱动表会被加载到内存遍历所有行,而被驱动表只能在磁盘遍历。假设驱动表有n条数据,被驱动表有m条数据。

如果索引表做驱动表。

对于驱动表来说,每行都要走一次,时间复杂度为N。

而被驱动表没有索引,也需要全表扫描,时间复杂度为N*M。

执行过程近似时间复杂度为N+N*M。

如果索引表做被驱动表

对于被驱动表来说,时间复杂度大概是logM,查询到主键回表又是logM,需要查询N次,总共时间复杂度为N*2 *logM。

因此执行过程近似时间复杂度是N+N*2 *logM。

所以索引表做被驱动表的话,会大大提升查询效率。

因此业务中,在join查询时出现慢查询情况,可以将被驱动表加上索引。

两个表都有索引

当两个表都有索引的时候,时间复杂度为N+N*2 *logM,N占主导地位。

因此选择表数据小的做驱动表

业务中,建议小表驱动大表。

两表都没索引

这时候你或许有疑问了,两表都没索引时间复杂度不都是遍历两张表全表吗?

当然是不同的,首先驱动表是在内存中遍历的,要比磁盘快。如果放入内存中的数据多一点,磁盘io次数就少了。性能不久提升了。

话是这样说的,但这里面有一个大坑。

先把结论放出来:

  • 如果此时两个小表。选择相对大的做驱动表。
  • 如果此时一个小表,一个大表。选择小表做驱动表。
  • 如果此时两个大表。选择相对小的做驱动表。

为什么这样做呢?

首先缓冲区是有大小限制的,并不是无限的。因此,放入过大的表就会放不下。所以尽量能放入能放下的表。

对于放不下的大表也有优化方法。

MySQL使用BNL算法,将大表分块放入缓冲区中,对于每块都对驱动表进行全表扫描。

join和left join区别

这时候你已经知道了join和left join的大致执行流程了。但你或许还不知道他俩区别到底在哪里。这里就来详细说说。

首先join时inner join的缩写,意思是找到两个表同时成立的数据。

而left join查找的结果除啦inner join的结果,还有左表剩余的结果,以及右表对应的null值。

一般来说left join语句左表是驱动表,而inner join语句是优化器选择驱动表。

为什么left join左表为驱动表

这里就和上面执行流程有关了。

大家回忆一下,驱动表是不是存储在内存当中。而left join结果是不是需要左表的所有数据。而右表返回的刚好是符合条件的数据。剩下的左表查询不到的直接返回null值,刚好结果集对应left join需要的结果。

如果left join将右表作为驱动表有什么后果呢?

首先右表遍历所有数据找到对应左表的符合条件数据作为结果集。然后再次去磁盘查找左表剩余的数据。

这时候效率显而易见的会变低,因此一般都会将左表作为驱动表。right join也同理。

left join特殊情况

当然,left join左表驱动不是一定存在的。

left join和inner join一样,在表中现根据on条件选出结果集。如果出现where语句的时候,where会对结果集进行筛除。这时候where就会将左表出现右表却没有匹配的数据都给筛除掉。

当出现where的时候,left join就跟inner join相同了,筛选出同时成立的数据行。此时left join就会转换为inner join,由优化器指定驱动表。

所以left join不一定左表一定是驱动表。


结语

每个人都有自己独特的才华和潜能,在这个广袤的世界上,你的存在是有意义的。无论你是谁,你的背景如何,你所处的环境怎样,只要你敢于跨出舒适区,付出努力,追求卓越,你就能够开创属于自己的辉煌。

我们下期见。

每一次努力都是一次进步,即使进展缓慢,也要坚持不懈。

往期文章推荐

  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱发博客的嗯哼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值