现在的位置: 首页 > 数据库 > 正文

为何需要Change Buffer?如何配置Change Buffer

2020年01月11日 数据库 ⁄ 共 2608字 ⁄ 字号 评论关闭

  Change Buffer是一种特殊的数据结构,缓存对二级索引页面的更改并且这些页面不在Buffer Pool中。缓存的changes可能由 Insert 、Delete 和 Update的结果导致。稍后在页面被其他读取操作加载到Buffer Pool的时候合并。

  简而言之:Change buffer的主要目的是将对二级索引的数据操作缓存下来,以此减少二级索引的随机IO,并达到操作合并的效果。

  与聚簇索引(ps:默认是InnoDB里的主键,主键是聚集存储的)不同,二级索引通常不是唯一的,并且插入二级索引的顺序相对随机。删除和更新可能会影响不在索引树中相邻的二级索引页。当受影响的页面被其他操作读入缓冲池时,合并缓存的更改,避免了从磁盘读取二级索引页到缓冲池所需的大量随机访问I / O。

  在MySQL5.5之前的版本中,由于只支持缓存insert操作,所以最初叫做insert buffer,只是后来的版本中支持了更多的操作类型缓存,才改叫change buffer,所以本文是基于MySQL5.5之后的版本。

  (Secondary Index(二级索引)

  1、也可以称为 非聚集索引

  2、叶子节点存储的是索引和主键信息

  3、在找到索引后,得到对应的主键,再回到聚集索引 中找主键对应的记录(row data))

  放出二级索引的解释可能还是懵,什么时候算作二级索引,所有主键以外的索引都是二级索引(innodb默认)。

  所以说根据主键访问数据(永远是效果最好的方式),原因看上方括号内二级索引介绍

  为何需要Change Buffer

  表的索引存于该表的ibd文件中,数据也存于此文件。表数据更新的同时也会更新对应的表的索引数据,所以:例如对表进行insert时,很可能会产生大量的物理读(物理读索引数据页),insert一个表,对应的表上面的索引会变动,索引不常使用,产生物理读,索引顺序和表不一致耗时。

  (物理读(Physical Reads):从磁盘读取数据块到内存的操作叫物理读,当缓存不存在这些数据块的时候就会产生物理读,物理读过大表现为磁盘 I/O 较高)

  所以将对索引的更新记录存入Change Buffer中,而不是直接调入索引页进行更新;选择时机进行merge insert buffer的操作,将insert buffer中的记录合并(merge)到真正的辅助索引中。

  系统大部分空闲时或在慢速关闭期间运行的清除(purge)操作会定期将更新的索引页写入磁盘。与每个值立即写入磁盘相比,purge操作可以更有效地为一系列索引值写入磁盘块。

  当有许多受影响的行和许多要更新的二级索引时,Change Buffer合并可能需要几个小时。在此期间,磁盘I / O会增加,这会导致磁盘绑定查询显着减慢。在提交事务之后,甚至在服务器关闭并重新启动之后,更改缓冲区合并也可能继续发生

  在内存中,Change Buffer占用Buffer Pool的一部分。在磁盘上,Change Buffer是系统表空间的一部分,其中的索引会在关闭数据库服务器时更改。

  配置Change Buffer

  对表执行 INSERT,UPDATE和 DELETE操作时, 索引列的值(尤其是secondary keys的值)通常按未排序顺序排列,需要大量I / O才能使二级索引更新。Change Buffer会缓存这个更新当相关页面不在Buffer Pool中,从而磁盘上的相关页面不会立即被读避免了昂贵的I / O操作。当页面加载到缓冲池中时,将合并缓冲的更改,稍后将更新的页面刷新到磁盘。该InnoDB主线程在服务器几乎空闲时以及在慢速关闭期间合并缓冲的更改 。

  为方便理解:来了一个关于二级索引页面的DML操作,并且这个页面没有在Buffer Pool内,那么把这个操作存入Change Buffer(MySQL5.5之前的版本叫Insert Buffer),ok,那么下一次需要加载这个页面的时候,也就是这个页面有需求的时候,会将Change Buffer内的更改合并到Buffer Pool,随后当服务器在空闲的时候,这个更改会刷到disk(磁盘)上。所以一开始那张很难读的图的流程就清晰了:(黄色箭头这样的走势)

  因为它可以减少磁盘读取和写入,所以更改缓冲区功能对于I / O绑定的工作负载最有价值,例如具有大量DML操作的应用程序(如批量插入)。

  但是,Change Buffer占用Buffer Pool的一部分,从而减少了可用于缓存数据页的内存。如果工作集几乎适合Buffer Pool,或者您的表具有相对较少的二级索引,则禁用Change Buffer可能很有用。

  毕竟Change Buffer只适用于Buffer Pool外的页面嘛。

  可以使用innodb_change_buffering 配置参数

  允许的innodb_change_buffering 值包括:

  all

  默认值:所有操作

  none

  不要缓冲任何操作。

  inserts

  缓冲插入操作。

  deletes

  缓冲区删除标记操作。

  changes

  缓冲插入和删除标记操作。

  purges

  缓冲在后台发生的物理删除操作。

  Change Pool内部结构

  ibuf代表Insert Buffer,可以直接将其看成Change Buffer,为MySQL 5.5 之前Change Buffer就叫Insert Buffer

  ibuf btree最大默认为buffer pool size的25%,当超过25%时,可能触发用户线程同步缩减ibuf btree。为何要将ibuf btree的大小和buffer pool大小相关联呢 ? 一个比较重要的原因是防止ibuf本身占用过多的buffer pool资源。

  配置Change Pool最大大小

  该innodb_change_buffer_max_size 变量允许将Change Buffer的最大大小配置为缓冲池总大小的百分比。默认情况下, innodb_change_buffer_max_size设置为25.最大设置为50。

  使用测试不同的设置的业务性能以确定最佳配置。该 innodb_change_buffer_max_size 设置是动态的,允许在不重新启动服务器的情况下修改设置。类似innodb_buffer_pool_size也可以在线更改那种。

抱歉!评论已关闭.