Description
最近开始读《MySQL技术内幕-InnoDB存储引擎》,感觉还是有很大的收获,读到 Insert Buffer
(注:2015年已改为Change Buffer
,书籍出版时间是2013)的时候,感觉收获挺大,在网上找了一些资料,这里做一点笔记。
概念解释
1.索引(Index)
索引是数据库中非常关键的一个概念和技术,它在加速查询方面起着【至关重要】的作用。InnoDB
中,所有的主键默认带有索引。主键的索引有一个别名叫聚集索引,非主键的其他列的索引叫辅助索引(secondary index)。
2.聚集索引(clustered index)
如上所述,主键的索引一般叫聚集索引,为什么要用“聚集”这个词呢,我的理解是,因为主键往往的自增的,这就带来一个线下就是,索引在一个页的那些行,它们对应的行内容在磁盘也是在一个页的。这就比较类似书的目录和内容的关系,在目录上比较接近的部分,它们所指向的内容,也往往是比较接近的。比如第N章和第N+1章常常都是挨着的。这样的结构带来的一个好处就是在批量插入时,比如一次插入1000行数据,那么这1000行数据的主键肯定是连着的,那么它们的索引也很可能在一个页,最终它们的存储也恰好是在一个页,这样就可以用两次(一次写索引,一次写内容)磁盘IO
(耗时)操作来完成,因为它们是连续的嘛。对于不连续的呢,就比较麻烦了。
3.辅助索引(secondary index)
既然有聚集索引,那么对应的就有非聚集索引——辅助索引。辅助索引为什么不聚集呢,因为它们所对应的列很有可能并没有什么关系。就是说两个索引可能距离比较近,但是这和它们的内容所在位置是没有任何关系,这就类似汉语字典里面的用偏旁部首查字音一样,【打】和【答】可能在内容上比较近,但是它们对应的目录,也就是偏旁部首却距离很远,一个在提手旁“扌”对应的内容里,一个在竹字头“竹”对应的内容里,可以说是十万八千里了。在这种情况下,要批量插入1000行数据时,内容因为主键自增的关系,可能仍然可以通过一次磁盘IO
就完成,但是我们的索引,却没有这么【聚集】,可能零零散散分布在若干个不同的页中,可能需要多次随机磁盘IO
,这效率就低很多了,几乎是无法接收了,于是Change Buffer
就出场了。
Change Buffer
1.Change Buffer
的含义
为了避免上文描述的因为索引零散分布造成的多次随机磁盘IO
,MySQL InnoDB
引入了 Change Buffer
,对于辅助索引的相关操作,并不会直接操作索引的页,而是先放到Change Buffer
中,在以一定的频率和情况进行Change Buffer
和索引的页的merge
操作,这样可以将多个操作合并成一个,极大的提高了对于非聚集索引的操作性能。
下面的这个MySQL
官方的图,很好的展示了这个过程
2.Change Buffer
的配置
Change Buffer
的缓冲的数据类型,由innodb_change_buffering
配置,默认为all
,表示包含所有类型,可选择的项有none
,inserts
,deletes
,changes
,purges
,分别表示配置相应类型。
innodb_change_buffer_max_size
用来配置Change Buffer
可以占用buffer pool
的最大百分比,默认为25,最大可以配置到50.
3.Change Buffer
的监控
使用以下命令可以查看Change Buffer
相关指标
mysql> SHOW ENGINE INNODB STATUS
在其输出的大量信息中,INSERT BUFFER AND ADAPTIVE HASH INDEX
包含了Change Buffer
相关的一些指标:
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 4425293, used cells 32, node heap has 1 buffer(s)
13577.57 hash searches/s, 202.47 non-hash searches/s
其中,size
表示Change Buffer
使用的页的数量,insert\delete mark\delete
分别表示各自的记录数,merges
表示合并的次数。
参考资料
1.https://mysqlserverteam.com/the-innodb-change-buffer/
2.https://dev.mysql.com/doc/refman/5.7/en/innodb-change-buffer.html
3.https://dev.mysql.com/doc/refman/5.7/en/glossary.html
4.https://dev.mysql.com/doc/refman/8.0/en/faqs-innodb-change-buffer.html#faq-innodb-change-buffer-current-size