select * from information_schema.innodb_metrics where name like '%ibuf%';
能够查看到change buffer 的相关信息。sql
建立张表app
CREATE TABLE `author_1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `index_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
author_1 有主键索引,和一个index_name 的二级索引。性能
假设该表存在如下数据优化
聚簇索引的结构相似于:ui
页6 | ||
1 | 2 | 3 |
abc | jack | zrr |
234 | 24 | 23 |
咱们知道二级索引 的value 存的是主键,例如此例子中二级索引
的结构相似于:atom
页65 | ||
abc | jack | zrr |
1 | 2 | 3 |
update author_1 set name = 'xxx' where id = 1
这个语句须要修改 2 个页面的数据。spa
更新流程是:日志
首先在 Buffer Pool 中查找对应的 页,(也就是页6, 和页65)code
这里产生了2种状况:orm
咱们知道磁盘IO 比较耗时,因此Mysql 为了优化这一步骤,引入了Change Buffer 。
首先强调:
那么也就是 主键,以及惟一索引 是用不了这个优化的。
对应到例子中, 即便引入了Change Buffer ,若是页6不在Buffer Pool 中,不管如何都须要从磁盘中读取,而后修改。
而页65,则不一样了:
这个时候页65,不须要从磁盘中进行读取了,InnoDB 会直接写一条信息到Change Buffer 中,而后写redo log 。这样无需进行磁盘IO就能够完成更新。
总结下 Change Buffer 只有 对非惟一的二级索引 的数据页 ,而且该数据页不存在Buffer Pool 中,才会被使用到。
另外说明一点:change buffer 和 redo log 的数据为了持久化是会被刷入磁盘的。 也许会有疑问?这还不是进行磁盘操做了吗? 是进行磁盘操做了,可是change buffer 和 redo log 都是进行顺序写效率较高 (磁盘顺序写 和 随机写 性能差别很大)
select * from school where name = 'xxx'
因为会用到 index_name 索引, 因此须要将页65 读取到Buffer Pool ,但咱们知道此时页面65页中 只有记录 'abc' ,那么读取页面65 以后,InnoDB 首先把 Change Buffer 中的数据 与读取的数据merge ,而后存储在Buffer Pool中,这个时候页65 中的数据就是正确的数据了。
道理很简答, 惟一索引 在插入修改时都要进行惟一判断。若是不读取数据没法进行判断,既然数据不管如何都必须读取到Buffer Pool 中 天然就不会用到Change Buffer 了。
change buffer 提高了对非惟一二级索引
的写性能。 若是业务上对字段没有惟一性要求,那么应该尽可能使用普通索引,避免惟一索引。对于写多读少的业务来讲,页面在写完之后立刻被访问到的几率比较小,此时 change buffer 的使用效果最好。这种业务模型常见的就是帐单类、日志类的系统。