Change Buffer是对更新过程有显著的性能提升。在更新数据的时候,如果数据页在内存中就直接更新,如果要更新数据的内存页不在内存中,就会在不影响数据一致性的前提下,数据库引擎会把更新操作缓存在Change Buffer中,这样就不需要从磁盘中读取数据页,在下一次查询这个数据页的时候从磁盘中读取这个数据页,然后将Change Buffer中记录的与这个数据页有关的操作执行,通过这样保证数据的准确,这个过程也叫做merge。
我们把更新操作先写入Change Buffer,减少读磁盘,更新语句的执行速度就会显著提升。将更新操作记录在Change Buffer然后一起merge,减少了数据读入内存,还可以提高内存利用率。
Change Buffer的merge在查询相关数据页的时候会被触发,系统后台线程也会定期merge,数据库正常关闭的时候也会先merge再关闭数据库。
为什么唯一索引不能使用Change Buffer?
唯一索引在每一次更新的时候都会先查询要插入的数据是否已经存在,这就必须把数据页读入内存中校验是否违反唯一性约束,如果已经将数据页读入内存了,直接更新内存就可以了。
假设我们要往一张表里插入一条数据,我们来看一下唯一索引和普通索引的处理流程有什么不一样的,我们分两种情况来看:要更新的数据页在内存中和要更新的数据页不在内存中。
一、要更新的数据页在内存中。
唯一索引:先找到要插入的位置,判断是否存在冲突,然后插入数据,执行结束
普通索引:先找到要插入的位置,插入数据,执行结束。
这种情况,唯一索引和普通索引对语句执行速度影响相差不大,也可以忽略不计。
二、要更新的数据页不在内存中。
唯一索引:先将数据页读入内存中,然后判断要插入的位置是否存在冲突,然后插入数据,执行结束。
普通索引:将更新记录写在Change Buffer中,执行结束。
唯一索引在这个时候就涉及到随机磁盘访问,这也是成本最高的操作之一。相应的,普通索引写Change Buffer就减少了随机磁盘访问,就可以显著提升性能。
所有的普通索引都可以使用Change Buffer?
到这里我们已经知道了Change Buffer对于普通索引的更新操作有加速作用,那么是所有的普通索引都可以使用Change Buffer进行加速吗?
这个时候我们就要具体业务具体分析,不同的场景使用不同的策略,Change Buffer我们可以看作是把变更记录缓存下来,所以在merge之前Change Buffer记录的变更记录越多,对性能的提升就越大。因此对于写多读少的业务场景使用效果就非常好,如归档系统、日志系统等。
对于写入之后很快就做查询的业务场景,使用Change Buffer,记录 了更新记录之后,很快查询就出发了merge,这样也不能降低随机磁盘访问,还增加了写Change Buffer,这个地方Change Buffer就反向操作了。如我们OMS系统的订单表,写入之后立马就会做一些了操作都需要查询。
总结
Change BUffer主要是改善更新操作的性能,建议尽量选择普通索引,如果写入之后就查询的业务场景,就要关闭Change Buffer,除了这种业务场景,Change Buffer都可以提升性能。