mysql之join buffer的作用

1. 一些要知道的概念

1.1 小表驱动大表

  • 在表连接过程中。一般选择小表作为驱动表,大表作为被驱动表。
  • 驱动表(小表)的连接字段无论建立没建立索引都需要全表扫描的被驱动表(大表)如果在连接字段建立了索引,则可以走索引。如果没有建立索引则也需要全表扫描。

1.2 两张表连接的情况

  • 被驱动表的连接字段有索引:主键索引
    • 对于驱动表中的每一条数据,到被驱动表聚簇索引上寻找其对于的数据。
  • 被驱动表的连接字段有索引:二级索引
    • 对于驱动表上的每一条数据,到被驱动表二次索引上寻找其对于的数据id,然后再根据数据id到聚簇索引上寻找对于的数据。
  • 被驱动表的连接字段没有索引
    • 对于驱动表上的每一条数据,都要到被驱动表上进行一次全表遍历,找到对应的数据。

1.3 join buffer的作用

  • 就是针对被驱动表的连接字段没有索引的情况下需要进行全表扫描,所以引入了join buffer内存缓冲区来对这个全表扫描过程进行优化。

2. mysql中表关联的算法

2.0 前提

  • 都是在被驱动表的连接字段没有索引的情况下mysql才会使用这些关联算法进行表连接。

2.1 嵌套循环连接 Nested-Loop Join(NLJ

  • 假设t1表数据是100,t2表数据是10000条
select * from t1 left join t2 on t1.name=t2.name;
  • 会先从表t1里拿出第一条记录row1,完了再用row1遍历表t2里的每一条记录,来寻找是否name字段是否相等,以便输出。然后循环这个过程,直到t1表里的所有的记录都取出。
  • 在整个过程中
    • t1表遍历了1遍。t2表遍历了100*1遍。即每层t1表中取出1条记录,都要遍历一遍t2表。
    • 因为这些文件都是在磁盘上的。想想在遍历t2表100遍过程中得有多少次IO操作呀。
    • 整个过程跟我们平时写程序的双重for循环本质是一样的。但是我们程序写的双重for循环是基于内存得,而mysql中这些却是基于磁盘的,需要将文件从磁盘调用内存,这样双重for循环,内表需要反复调入内存。
    • 假设将表t2。全部调入内存需要10次IO。即每次调入1000条记录。则在t2表的100次遍历过程中需要调用IO次数为 10*100=1000次IO。

2.2 块嵌套循环连接 Block Nested-Loop Join(BNLJ

  • 基于嵌套循环查询的问题,mysql进行了优化,采用块嵌套循环连接。
  • 它多了一块内存缓冲区join buffer。
  • 在这个过程中,不再是每次从t1表中取1条记录。而是在开始时用内存缓冲区join buffer将t1表全部装入内存每次取t2表的1000条记录调入内存。然后,让t1表t2表在内存的这一部分(t2表在内存的这一部分作为外层循环,t1表作为内层循环)通过双重for循环进行匹配,然后循环这个过程,直到t2表的10000条数据都调入内存一次(即需要十次IO调入)。
  • 在整个过程中
    • t1表遍历了1*10000遍,t2表遍历了1遍。再结合表的大小,其实匹配的总的次数是一样的
    • 但是变化的是IO次数。在整个过程中,t1表一开始调入内存,需要一次IO。而t2表也只是将表调入内存一次,需要10次IO。IO的次数是少了两个量级。

 2.3 hash join算法

  • 在mysql8.0中出现的新算法
  • 也是用了join buffer来做内存缓存。
  • 它在join buffer中以外表为基础建立了一张hash表。内表通过hash算法来跟hash表进行匹配
  • hash join其实利用上了hash索引,减少了内表的匹配次数。而且IO次数跟BNLJ差不多。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值