在InnoDB中,当对应的数据不存在与Buffer Pool中时,为了避免大量的随机磁盘I/O可能带来的性能瓶颈,InnoDB 在Buffer Pool 中划分出一部分内存,称为Change Buffer,由其负责缓存由DML操作引起的二级索引相关数据的变化。当对应的数据下次被读入Buffer Pool 中时,Change Buffer 中记录的变化信息会被合并到数据中。其结构如下图所示。简要的,使用Change Buffer有三个要点:a. DML操作, b. 涉及二级索引,c. 对应page不存在于Buffer Pool中。
与聚簇索引不同,二级索引通常是非唯一的,并且对其对应列的插入操作也通常是随机的,同一次更新或者删除需要操作的数据可能并不是在索引树相邻的位置。因此InnoDB采用的 Change buffer来缓存二级索引相关列对应数据的变化,并在后续数据读取至buffer pool中时进行合并,再由磁盘同步操作(Flushing)将变化的数据同步至磁盘中,flushing操作其效率相比于分散的随机将数据写入磁盘,其效率更高。
Change Buffer 其目的主要是减少DML操作可能引起的大量随机磁盘I/O,所以对于具有大量数据更新的场景,其价值更高。比如对于频繁的批量数据插入场景。但需要注意的是,当有数据更新操作导致大量数据或二级索引发生变化时,change buffer 向 buffer pool的合并将会进一步引起大量的数据flushing,进而导致大量的I/O占用,可能引起需要读取磁盘的查询性能下降。
配置Change Buffer
如前所述,Change Buffer 是由 Buffer Pool 中划分出的一部分区域。由于内存的珍贵性,当Buffer Pool足够大,足以缓存全部的数据时,可以将其关闭。因为此时将更新的数据缓存至Change Buffer的条件不成立。
对于何种操作导致的数据更新需要缓存至Change Buffer,Mysql 提供 innodb_change_buffering 参数进行控制,其默认值为all,可选的配置有如下选项:all 所有操作,包括inserts, deletes, purges
none
inserts 插入操作
deletes 当数据被标记为删除时
purges 当数据被物理删除时
Change Buffer 占用内存的大小由参数 innodb_change_buffer_max_size 控制,表示其占用 Buffer Pool 的最大比例,是一个比例参数,其默认值为 25, 最大可以设置为50。对于大量写的场景,可以考虑适当将该参数设置较大,而对于数据相对变化不大,主要负载为读的场景,可以考虑将该参数设置为较小的值。
【Reference】
1. MySQL 5.6 Reference Manual