/* 1.在innodb中每一个数据页的大小默认是16KB 2.对于普通索引来讲,在查询时查到知足条件的第一天记录的时候须要查找下一个记录,直到碰到第一个不知足 k=5 条件 的记录 3.对于惟一索引来讲由于定义了惟一性,因此查到第一个知足条件的记录后就会中止查询 普通索引和惟一索引的性能差别微乎其微 change buffer 在内存中有缓存这mysql数据页,若是在更新的时候,把磁盘内容改了,可是内存数据还没改回出现数据不一致,这时候就须要 change buffer,innodb会将这些更新操做缓存在change buffer,下次若是须要访问这个数据页,将这个数据页读入内存,而后执行change buffer中有关这个数据页的操做,最终仍是会将数据写入磁盘。 change buffer 这个操做应用到原数据页,获得新结果的过程叫作merge 那么什么状况下可使用change buffer? 惟一索引;对于惟一索引来讲,全部的更新操做多会先判断这个操做是否违反了惟一约束,好比要插入一条(4,400)须要先判断一下表中是否存在k=4这条记录,而且是必需要将数据页读入内存才能判断。若是都已经读入内存了,,那直接更新内存会更快,就不必使用change buffer, 所以惟一索引的更新就不能使用change buffer了,实际上也只有普通索引可使用 change buffer 用的是 buffer pool 里的内存,所以不能无限增大。change buffer 的大小,能够经过参数 innodb_change_buffer_max_size 来动态设置。这个参数设置为 50 的时候,表示 change buffer 的大小最多只能占用 buffer pool 的 50%。 第一种状况:这个更新的目标记录在内存中,在innodb中一条更新操做是如何执行的,一条新数据(4,500) 惟一:找到3和5的这个位置判断有没有冲突,若是没有插入数据。 普通:找到3和5的位置,插入数据 他们的区别是多了一个判断,这对于cpu来讲差别很微小 第二种状况:这个记录要更新的目标数据页不在内存中 惟一:先将目标数据页读入内存中,判断目标是否冲突,再来写入 普通:将更新操做记录在change buffer中,执行结束 change buffer减小了对磁盘的随机访问,因此对更新的性能提高仍是明显的 change buffer的应用场景 经过上面咱们知道change buffer对更新操做的加速过程,且只限于普通索引,而不适用于惟一索引。 问题:普通索引的全部应用场景都适用于change buffer吗? change buffer是将咱们对一个数据页的更新操做记录下来,因此在一个数据页作merge前,change buffer记录的变动越多(也就是更新次数越多),收益越大 所以对于写多读少的业务来讲,页面在写完立刻被访问的几率小,此时使用change buffer的效果最好 这种常见业务有,帐单,日志等 反之,若是一个业务写完立刻就作查询,那么即便知足条件,将更新先记录在change buffer,但立刻进行访问,会当即触发merge过程,这样随机访问IO次数并不会减小,还会增长change buffer 的维护代价,因此这种业务使用change buffer反而会起副作用。 因此普通索引和惟一索引到底该如何选择 咱们知道在查询方面他们是没什么差异,主要是考虑在更新上面的性能。因此尽可能选择普通索引 若是在更新后立刻会进行查询操做,应该关闭change buffer ,而在其余状况下change buffer都能有明显的性能提高 如何开启关闭change buffer呢? 能够经过参数innodb_change_buffering来控制是否启用change buffer。 --all: 默认值。开启buffer inserts、delete-marking operations、purges --none: 不开启change buffer --inserts: 只是开启buffer insert操做 --deletes: 只是开delete-marking操做 --changes: 开启buffer insert操做和delete-marking操做 --purges: 对只是在后台执行的物理删除操做开启buffer功能 为何change buffer可以支持数据持久化呢? change buffer 会将操做记录在redo log若是服务器意外关闭,在redo log这个日志文件中还有记录 redo log 这个主要是用来节省随机写入IO磁盘的消耗(转为顺序写) 而change buffer这个是来节省随机读IO磁盘的消耗 */