在向一个表进行insert、delete或update操作时,里面的索引(聚集索引和非聚集索引)也会随即更新,其中,主键(聚集索引)是按照顺序进行插入的,而非聚集索引则会分散地插入。顺序读写的速度要比随机读写的速度快,表越大就越明显,而插入的性能就会降低。
因此在MySQL5.1.X版本里,InnoDB引入了一种优化措施,当一个表做insert操作来更新非聚集索引时,如果该非聚集索引页被读入Innodb_Buffer_Pool缓冲池里,那么就直接更新非聚集索引,并使用正常的写脏数据块方法将其闪存到磁盘中;如果没有读入缓冲池里,则使用插入缓冲区来缓存非聚集索引页的变化,直到该页被读入Innodb_Buffer_Pool缓冲池里,执行插入缓存合并操作,并使用正常的写脏数据块方法将其闪存到磁盘中,从而提高了插入性能。
然而,由于插入缓冲区占用部分Innodb_Buffer_Pool缓冲池,因此使得缓存数据页的可用内存减少了。如果数据和索引全部读入Innodb_Buffer_Pool缓冲池,并且表中有相对较少的非聚集索引,那么就可以关闭 InnoDB的插入缓冲功能。前面也介绍了,如果该非聚集索引页被读入Innodb_Buffer_Pool缓冲池里,那么就会直接更新非聚集索引,并使用正常的写脏数据块方法将其闪存到磁盘中,这样一来,插入缓冲区就没有什么作用了,并且还占用一定的内存,这种情况下关闭该功能较好。
从MySQL5.5.X版本开始,还为删除操作扩展了同样的功能(首先是删除标记操作,然后使用收集/清除所有已删除记录的清除操作)。现在可以使用innodb_change_buffering 配置参数来控制删除缓冲和既有插入缓冲功能,默认是all,此参数支持动态设置:
SET GLOBAL innodb_change_buffering = all;
关于innodb_change_buffering参数的介绍,请参见MySQL5.5手册: