当前位置:首页 > 每日看点

mysql 连表查询使用join 和 where 区别大么? 两个表用=和join连接什么区别?

卡卷网1年前 (2025-01-13)每日看点295

为什么很多人不推荐mysql连表join查询

join查询是什么?是连表查询,我们需要两个表的数据,就会使用join来进行连表。那么mysql里面是怎么连表的呢?它和我们自己查询出一张表的数据在遍历去查询另外一个表是不是一样呢?

join查询

join查询还可以写成left join,表示的是根据左边的表来查询右边的表。但实际上,优化器会进行优化,选择合适的表来做驱动表,不一定是左边的表。

Index Nested-Loop Join

NLJ算法,这是一种基于索引的算法,如果你的连表用到了索引,则会使用这个算法。

比如下面的查询语句:

b.uid字段有索引,并且假设a是小表,优化器选择了a表作为驱动表,b表作为被驱动表。

select * from a left join b on a.id = b.uid;

执行流程大致如下:

  1. 1. 读取表a的第一行数据
  2. 2. 使用表a的id去b表的索引树上查询到对应的b表id
  3. 3. 通过查询的b表id回表查询b表数据
  4. 4. 把a表和b表数据放在一起
  5. 5. 重复上面的步骤直到a表遍历完成
  6. 6. 返回数据

可以看到这和我们自己查询出一张表然后遍历查询过程是一样的。

但是它的优势是省略了多次连接数据库,连接数据库是比较耗费资源和时间的,这样来看,使用join是更加好的选择。当然前提是你的join被驱动表有索引。

这个过程扫描了整个表a和表a的id对应的每一行表b。假设a表的数据量是n,那么扫描了n + n行,当然不算回表。如果算上回表其实相当于n + n + n行。

我们再看一下这个算法的时间复杂度。

b+树中,定位一个记录的时间复杂度大约是log(m)。m是b表的数据行数。为什么这里使用了b表的数据行数而不是上面说的a表的行数呢,因为这里指的是b表索引树的时间复杂度,当然是跟b表索引树大小挂钩也就是b表数据大小挂钩了。如果在算上回表查询,那么时间复杂度大约是2log(m)。

a表要进行全表扫描,那么a表的时间复杂度就是n,再加上每一行要去b表中查询,那么去b表查询的时间就是n * 2log(m)。加起来就是n + (2nlog(m))。

这里面2是常量可以忽略不记,而且2是因为回表造成的,如果我们使用覆盖索引,那么这个2就可以去掉了。

nlog(m) 比 n小,所以显然n的影响是最大的。也就是说n越小,那么我们连表的速度就越快。所以我们连表的时候要使用更小的那张表作为驱动表,然后给被驱动表的连表字段上面加上索引或者覆盖索引。这样我们的连表其实还是很快的。

Block Nested-Loop Join

如果你的被驱动表字段上面没有索引,那么mysql就会使用另外一种算法。这个算法叫BNL算法。

本来没有索引的情况下,按照上面的流程应该是下面这样:

  1. 1. 读取表a的第一行数据
  2. 2. 使用表a的id去b表上进行全表扫描查询到对应的b表数据
  3. 3. 把a表和b表数据放在一起
  4. 4. 重复上面的步骤直到a表遍历完成
  5. 5. 返回数据

这样的话对于每一行表a的数据都要进行b表的全表扫描,也就是如果表a记为n行,表b记为m行,那么需要扫描n * m + n行数据。和上面的n + (2nlog(m))相比,可以看到慢了多少倍。

所以mysql使用了另外一种方法,也就是BNL算法,这个算法做了一下优化,流程变成了下面这样:

  1. 1. 读取表a的所有数据放入join buffer
  2. 2. 对表b进行全表扫描,然后把每一条数据和join buffer中的数据做对比。
  3. 3. 把满足条件的数据返回。

这样的话,也就是扫描了一遍表a和表b,那么需要扫描n + m行数据。可以看到比上面的n + (nm)来说少了n倍的扫描量。当然了,这个算法,还需要在join buffer中进行nm次对比数据,但是这样内存判断也要比上面的方法好很多。

同样的这个算法对于两张表都是全表扫描,也就无所谓上面说的需要小表做驱动表了,反正都一样,都要全表扫描。

join buffer存在内存中,那么他就有大小的限制,参数join_buffer_size就是限制join buffer大小的。默认值是256k。如果表a的数据大于join buffer的大小,那么就会分段,也就是分多次进行。

但是分多次执行就会有一个问题了。比如分成了c次,那么表b就要经历c次的全表扫描。所以内存允许,当然Join buffer大一点速度会快一些。

这样的话就不是上面的n + m了,而是变成了n + (c*m),c是根据join buffer大小和n的大小来决定的。如果n越小或者join buffer size越大,那么c就越小。也就是说,如果我们使用小表作为驱动表,那么在遇到数据量超过join buffer的时候,速度也会比较快。

总结

总的来说,Join的时候注意下面几点:

  • • 总是用小表作为驱动表比较好。
  • • 能加索引就在被驱动表join字段上面加索引,使用NLJ算法而不是BNL算法。
  • • 在没有索引,并且驱动表数据量过大时,可以通过调大join_buffer_size的值来加速连表查询。

扫描二维码推送至手机访问。

版权声明:本文由卡卷网发布,如需转载请注明出处。

本文链接:https://www.kajuan.net/ttnews/2025/01/9191.html

分享给朋友:

相关文章

逾期后支付宝微信被冻结,显示执保该怎么办?

这几天有朋友问我说,他的微信零钱突然的用不了,问我是不是被冻结了,问我该怎么办?是不是被起诉了?这个,那个,别慌,别慌,还是那句老话:有钱就去协商,没钱只能暂时不管!但是真不管,这个被冻结的微信怎么办呢?今天针对这个问题,我就给大家做一哥比…

什么软件可以看电视直播?

什么软件可以看电视直播?

2024年9月6日最新更新:本文列举的 所有看电视直播、或流媒体影视资源点播的软件,我这两天又重新梳理成最新版本,最大程度保证可用性。获取方式见文末图片,或见评论。后续我也将持续更新,文章是旧的软件也会是新的,保证都是最新可用版本。作为一个…

4499 元起的荣耀Magic7 系列实际使用体验怎么样,值得入手吗?

全是软文。。。。。。不过我买了,标准版。为什么买荣耀:屏幕看着舒服,玩游戏选择大屏,超声波指纹解锁。其它,系统、续航、充电、拍照,不是最强,但均衡下来短板都不是很短。其它米OV,IQ、一加,都看了,预算有限,米OV的小屏不感兴趣,OPPO硬…

腾讯文档回收站彻底删除文件真的找不回来了吗?

趁早打电话联系腾讯文档的人可能还有救,一般这种都是数据库里标记为删除,文件还没有实际删除,然后经过一段时间后程序统一进行真删除。这个“一段时间”可长可短,可能是一小时也可能是几天几个月甚至几年,要看腾讯服务器的程序是怎么写的。 不过你联系腾…

为什么大家都说手机性能永远超不过PC?

最新的天玑9400牛逼吧,堪称PC级CPU,测试成绩16W功耗能跑9500分,1.8W能跑3000分,GPU也差不多是这个情况。 手机电池一般是4000-5000毫安时,电压3.7V。 也就是说,手机正常满载5W功耗下,这个电池能支持运行4…

为什么扫码支付在中国流行,在发达国家被排斥?

因为这是一种落后的技术。 卖菜的大爷花5毛钱就可以打印出一张二维码来接受付款。 你觉着这种先进么?跟先进完全不沾边的。正是因为不先进,所以才能流行。 卖菜大爷用不起一台先进的、具有NFC感应功能的、还能刷各种银行卡的收款机。 这就是现实。…

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。