一.insert buffer
性能改善
insert buffer和数据页一样,也是物理页的一个组成部分。
在innodb存储引擎中,主键是行唯一的标识符。通常应用程序中行记录的插入顺序是按照主键递增的顺序进行插入的。因此,插入聚集索引一般是顺序的,不需要磁盘的随机读取。但是一张表上有多个非聚集的辅助索引,在进行插入操作时,数据页的存放还是按主键进行顺序存放的,但是对于非聚集索引叶子节点的插入不再是顺序的了,这时就需要离散地访问非聚集索引页,由于随机读取的存在而导致了插入操作性能下降。
innodb存储引擎开创性的设计了insert buffer,对于非聚集索引的插入或更新操作,不是每一次直接插入到索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,若在,则直接插入;若不在,则先放入到一个insert buffer对象中,好似欺骗,数据库这个非聚集的索引已经插到叶子节点,而实际并没有,只是存放在另一个位置,然后再以一定频率和情况进行insert buffer和辅助索引叶子节点的merge操作,这时通常能将多个插入合并到一个操作中(因为在一个索引页中),这就大大提高了对于非聚集索引插入的性能。
insert buffer的使用需要同时满足以下两个条件:
1.索引是辅助索引
2.索引不是唯一的
缺点
应用程序进行大量的插入操作,这些都设计不唯一的非聚集索引,也就是使用insert buffer,若此时mysql数据库发生了宕机,这时势必有大量的insert buffer并没有合并到实际的非聚集索引中去。因此这时恢复可能需要很长的时间,在极端情况下甚至需要几个小时
辅助索引不能是唯一的,因为在插入缓冲时,数据库并不去查找索引页来判断插入的记录的唯一性。如果去查找肯定又会有离散读取的情况发生,从而导致insert buffer失去了意义
show engine innodb status\G;
innodb 1.2.x之前
seg size 显示了当前insert buffer的大小
free list len代表了空闲列表的长度
size代表了已经合并记录页的数量
inserts代表了插入的记录数
merged recs代表了合并的插入记录数量
merges代表合并的次数,也就是实际读取页的次数。merges:merges recs大约为1:3,代表了插入缓冲降对于非聚集索引页的离散io逻辑请求大约降低了2/3
问题
在写密集的情况下,插入缓冲会占用过多的缓冲池内存(innodb_buffer_pool),默认最大可以占到1/2的缓冲池内存
change buffer(可将其视为insert buffer的升级)
insert buffer 、delete buffer 、purge buffer
对一条记录进行update操作可能分为两个过程:
1.将记录标记为已删除
2.真正将记录删除
因此delete buffer对应update操作的第一个过程,即将记录标记为删除。purge buffer对应update操作的第二个过程,即将记录真正的删除。
innodb_change_buffering:用来开启各种buffer 的选项
从innodb 1.2.x版本开始,可以通过参数innodb_change_buffer_max_size来控制change buffer最大使用的数量
内部实现
insert buffer的数据结构是一颗b+树,现在的版本中,全局只有一颗insert buffer b+树,负责对所有的表的辅助索引进行insert buffer,而这颗b+树存放在共享表空间中,默认也就是ibdata1,。因此,试图通过独立表空间ibd文件恢复表中数据时,往往会check table失败。这是因为表的辅助索引中的数据可能还在insert buffer中,所以通过ibd文件进行恢复后,还需要进行repair table操作来重建表上所有的辅助索引。