Change Buffer的處理過程
對非唯一的普通索引的新增或更新操作,如果索引B+樹的需要新增或更新的數據頁不在內存中,則直接更新change buffer,等到后面需要使用這個數據頁(真正讀到內存中來)的時候,再根據change buffer在內存中做merge合並操作。
Change Buffer有什么好處?
先想想沒有change buffer時候,在緩沖池中沒有對應數據頁時會怎么更新。概括來說,有兩個步驟:
- 首先需要從磁盤中讀取對應的數據頁到內存中
- 然后更新內存中的數據頁。
首先分析主鍵索引或者非主鍵索引中的唯一索引,插入或者更新的操作。
- 主鍵如果是自增的,只需要讀取順序讀取磁盤中的頁,然后插入最新的行即可。主鍵如果是非自增的或者是自己設置的值,那么可能需要做一次隨機磁盤IO操作,讀取到對應的頁,做一下唯一性判斷,然后插入數據即可。
- 針對非主鍵索引中的唯一索引,大概率需要做隨機磁盤IO讀取,然后判斷唯一性,再插入對應的行。
所以對於主鍵索引和非主鍵的唯一索引,因為有唯一性判斷,所以更新操作時,必須要從磁盤中讀取數據頁,判斷唯一性,然后才能確定這個更新操作是否成功,即這個磁盤的IO操作是不可避免的。
對於非唯一索引來說,其實步驟也是類似的。但是因為不需要做唯一性判斷,所以為了提高更新的性能,Mysql給出的解決方案就是使用change buffer來保存對非唯一索引的更新。也就是說,當需要更新非唯一索引時,直接操作change buffer,成功即可返回。
那么什么時候會真正更新數據頁呢?有兩種情況會觸發:
- 被動:在后續的真正需要讀這個非唯一索引時,把索引的數據頁從磁盤讀取到內存中,再通過change buffer做一個merge操作,merge操作以后,內存中的數據頁就是最新的了。
- 主動:innoDB引擎中有線程會主動的定期做merge操作
業務實踐
- 利用普通索引的change buffer特性,當業務場景中的寫遠大於讀時,常見場景為日志表,當某些列必須建立索引時,可以考慮建立普通索引,提高寫入性能。
- 如果業務場景的寫之后立即伴隨讀,如果列的值是唯一的
- 那么其實建立普通索引是不合適的,因為寫的過程,雖然利用了change buffer暫時提高了寫的性能,但是在讀的時候還是需要磁盤IO。可以考慮建立唯一索引,在索引寫的時候,就提前讀取數據到緩沖池中,提高讀的性能。