【MySQL笔记】InnoDB的插入缓存+非聚簇索引插入的离散性理解

文章目录

  • [为什么需要插入缓存Insert Buffer](#为什么需要插入缓存Insert Buffer)
  • [Insert Buffer](#Insert Buffer)
    • [查看Insert Buffer信息](#查看Insert Buffer信息)
  • [Insert Buffer的问题](#Insert Buffer的问题)
  • [Change Buffer](#Change Buffer)
  • 总结
  • Reference

为什么需要插入缓存Insert Buffer

磁盘中的主键索引由于天然自增,无须磁盘的随机 I/O,只需不断追加。但普通索引大概率无序,默认情况下需要进行随机磁盘 I/O 操作,效率极差

磁盘随机IO:B+数索引是按页存储的,随机IO就是随机访问页中的数据

因此需要插入缓存(Insert Buffer)解决普通索引插入效率低下的问题

非聚簇索引插入的离散性

《MySQL技术内幕》中有这样一句话"B+树的特性决定了非聚集索引插入的离散性",下面先稍微理解下。

sql 复制代码
create table tb_user ( 
		id int auto_increment, 
		name varchar(20),
		age int unsigned,
		primary key (id),
		key(age)
 ) engine=innodb  default charset=utf8;

上面建的表中有三个字段:

  • id:自增主键
  • age:普通key,等于是非聚集索引
  • name:普通字段

往里面插入几条数据后如下:

此时,如果插入主键索引(递增),由于主键索引是有序 递增的,连续插入的操作是连续的,比如id=6,7,8都依次插入到最后就行,B+树结构也不太会受影响(因为主键索引叶子节点也是按主键顺序存储),也不需要额外的磁盘随机IO,比较快。

如果插入非聚簇索引(二级索引)age的值,由于age列的数据是无序 的,无法做到连续的索引插入到连续的行中,比如age=21, 22, 23,只能一条一条地定位和插入,这就是"离散"。在非聚簇索引的B+树中,叶子节点存储的是非聚簇索引与主键索引的值,虽然排序是按照age的大小,但插入操作并不是只考虑这个顺序,还是需要搜索定位到特定的**数据页(innoDB 数据页就是主键索引b+树的叶子节点,按主键索引顺序存储)**再插入,插入后还要考虑数据页容量大小决定是否分裂。

总之,主键索引由于自增特性,插入操作也是连续的 ,比较快;非聚簇索引字段在数据页中 可能是无序,插入需要定位对应的数据页(主键索引B+树叶子结点),因此插入操作是离散的,相对较慢。

Insert Buffer

对于满足以下条件的索引:

  • 非聚簇索引:因为聚簇索引,或者说主键索引一般是自增的且唯一的,插入操作连续,不存在非聚簇索引的问题
  • 索引不唯一:索引唯一的话,每次插入还需要通过磁盘随机I/O判断插入索引值是否已存在

不直接插入到磁盘的索引叶中,先判断对应的非聚簇索引是否在Buffer Pool中,如果在则直接插入,否则先放入Insert Buffer中,然后以一定频率和辅助索引页子节点进行merge insert buffer,此时通常能将多个插入合并到一个操作中,因此能提高插入性能。

查看Insert Buffer信息

sql 复制代码
SHOW ENGINE INNODB STATUS

INSERT BUFFER AND ADAPTIVE HASH INDEX 下面就是insert buffer的信息,包括:

  • seg size :当前Insert Buffer的大小,就是多少个数据页(insert buffer本身就是一个B+树,一个数据页16KB)
  • free listlen :空闲列表的长度
  • size :已经合并记录页的数量
  • Inserts :插入的记录数
  • merged recs :合并的插入记录数量
  • merges :合并的次数,也就是实际读取页的次数

Insert Buffer的问题

因为Insert Buffer信息也存储在buffer pool中,在写密集的情况下,可能会占用过多的buffer pool(默认最大可以占用到1/2),影响其他使用buffer pool的操作

Change Buffer

就是MySQL 5.5 之后的升级版本,可以理解为对所有的表更改操作(INSERT、DELETE、UPDATE)都做buffer,包括:

  • Insert Buffer
  • Delete Buffer
  • Purgebuffer

原来的Insert Buffer只对插入操作做buffer

总结

Insert Buffer 就是用于提升非聚集索引页的插入性能的,其数据结构类似于数据页的一个B+树,物理存储在共享表空间ibdata1中 。

Reference

https://cloud.tencent.com/developer/article/1735580

https://segmentfault.com/q/1010000013687775

https://zhuanlan.zhihu.com/p/333167012

相关推荐
程序员Xu40 分钟前
【OD机试题解法笔记】连续出牌数量
笔记·算法·深度优先
彤银浦1 小时前
Web学习笔记2
笔记·学习
长风破浪会有时呀1 小时前
Git 学习笔记
笔记·git·学习
偷偷的卷1 小时前
【算法笔记 day three】滑动窗口(其他类型)
数据结构·笔记·python·学习·算法·leetcode
亲爱的非洲野猪2 小时前
Oracle与MySQL详细对比
数据库·mysql·oracle
Matrix702 小时前
Navicat实现MySQL数据传输与同步完整指南
数据库·mysql
凤年徐2 小时前
【数据结构】时间复杂度和空间复杂度
c语言·数据结构·c++·笔记·算法
shepherd1112 小时前
批量update实现方案全面解析与最佳实践,带你掌握到底怎么批量更新最快、性能最高
后端·mysql
茫忙然2 小时前
【WEB】Polar靶场 Day8 详细笔记
笔记
飞升不如收破烂~2 小时前
英语笔记1.0
笔记