InnoDB存儲引擎有三大特性非常令人激動览祖,它們分別是插入緩沖膳殷、兩次寫和自適應(yīng)哈希膨疏,本篇文章介紹其中一個特性 - 插入緩沖(insert buffer)别智,在InnoDB的內(nèi)存中有單獨一塊叫“插入緩沖”的區(qū)域宗苍,下面我們詳細來介紹它。
非聚集索引寫性能問題
為了闡述非聚集索引寫性能問題薄榛,我們先來看一個例子:
mysql>create table t (
? ? ? ? ? id int auto_increment,
? ? ? ? ? name varchar(30),
? ? ? ? ? primary key (id));
我們創(chuàng)建了一個表讳窟,表的主鍵是id,id列是自增長的敞恋,即當(dāng)執(zhí)行插入操作時丽啡,id列會自動增長,頁中行記錄按id順序存放硬猫,不需要隨機讀取其它頁的數(shù)據(jù)补箍。因此,在這樣的情況下(即聚集索引)啸蜜,插入操作效率很高馏予。
但是,在大部分應(yīng)用中盔性,很少出現(xiàn)表中只有一個聚集索引的情況,更多情況下呢岗,表上會有多個非聚集的secondary index (輔助索引)冕香。比如蛹尝,對于上一張表t,業(yè)務(wù)上還需要按非唯一的name字段查找悉尾,則表定義改為:
mysql>create table t (
? ? ? ? ? id int auto_increment,
? ? ? ? ? name varchar(30),
? ? ? ? ? primary key (id),
? ? ? ? ? key (name));
這時突那,除了主鍵聚合索引外,還產(chǎn)生了一個name列的輔助索引构眯,對于該非聚集索引來說愕难,葉子節(jié)點的插入不再有序,這時就需要離散訪問非聚集索引頁惫霸,插入性能變低猫缭。
插入緩沖技術(shù)機制
為了解決這個問題,InnoDB設(shè)計出了插入緩沖技術(shù)壹店,對于非聚集類索引的插入和更新操作猜丹,不是每一次都直接插入到索引頁中,而是先插入到內(nèi)存中硅卢。具體做法是:如果該索引頁在緩沖池中射窒,直接插入;否則将塑,先將其放入插入緩沖區(qū)中脉顿,再以一定的頻率和索引頁合并,這時点寥,就可以將同一個索引頁中的多個插入合并到一個IO操作中艾疟,大大提高寫性能,master thread主線程其中的一項工作就是每秒中合并插入緩沖(可能)开财。
這個設(shè)計思路和HBase中的LSM樹有相似之處汉柒,都是通過先在內(nèi)存中修改,到達一定量后责鳍,再和磁盤中的數(shù)據(jù)合并碾褂,目的都是為了提高寫性能。
插入緩沖的啟用需要滿足一下兩個條件:
1)索引是輔助索引(secondary index)
2)索引不適合唯一的
如果輔助索引是唯一的历葛,就不能使用該技術(shù)正塌,原因很簡單,因為如果這樣做恤溶,整個索引數(shù)據(jù)被切分為2部分乓诽,無法保證唯一性。
插入緩沖帶來的問題
任何一項技術(shù)在帶來好處的同時咒程,必然也帶來壞處鸠天。插入緩沖主要帶來如下兩個壞處:
1)可能導(dǎo)致數(shù)據(jù)庫宕機后實例恢復(fù)時間變長。如果應(yīng)用程序執(zhí)行大量的插入和更新操作帐姻,且涉及非唯一的聚集索引稠集,一旦出現(xiàn)宕機奶段,這時就有大量內(nèi)存中的插入緩沖區(qū)數(shù)據(jù)沒有合并至索引頁中,導(dǎo)致實例恢復(fù)時間會很長剥纷。
2)在寫密集的情況下痹籍,插入緩沖會占用過多的緩沖池內(nèi)存,默認情況下最大可以占用1/2晦鞋,這在實際應(yīng)用中會帶來一定的問題蹲缠。