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 的使用效果最好。這種業務模型常見的就是帳單類、日誌類的系統。