[MySQL] InnoDB三大特性之
阿新 • • 發佈:2018-12-31
InnoDB儲存引擎有三大特性非常令人激動,它們分別是插入緩衝、兩次寫和自適應雜湊,本篇文章先介紹第一個特性 - 插入緩衝(insert buffer)
id int auto_increment,
name varchar(30),
primary key (id));
我們建立了一個表,表的主鍵是id,id列式自增長的,即當執行插入操作時,id列會自動增長,頁中行記錄按id順序存放,不需要隨機讀取其它頁的資料。因此,在這樣的情況下(即聚集索引),插入操作效率很高。
mysql>create table t (
id int auto_increment,
name varchar(30),
primary key (id),
key (name));
這時,除了主鍵聚合索引外,還產生了一個name列的輔助索引,對於該非聚集索引來說,葉子節點的插入不再有序,這時就需要離散訪問非聚集索引頁,插入效能變低。
MySQL - 淺談InnoDB儲存引擎》中提到的master
thread主迴圈其中的一項工作就是每秒中合併插入緩衝(可能)。
1)索引是輔助索引(secondary index)
2)索引不適合唯一的
如果輔助索引是唯一的,就不能使用該技術,原因很簡單,因為如果這樣做,整個索引資料被切分為2部分,無法保證唯一性。
1)可能導致資料庫宕機後例項恢復時間變長。如果應用程式執行大量的插入和更新操作,且涉及非唯一的聚集索引,一旦出現宕機,這時就有大量記憶體中的插入緩衝區資料沒有合併至索引頁中,導致例項恢復時間會很長。
2)在寫密集的情況下,插入緩衝會佔用過多的緩衝池記憶體,預設情況下最大可以佔用1/2,這在實際應用中會帶來一定的問題。
在上一篇《MySQL - 淺談InnoDB儲存引擎》中,我們可以看到在InnoDB的記憶體中有單獨一塊叫“插入緩衝”的區域,下面我們詳細來介紹它。
非聚集索引寫效能問題
為了闡述非聚集索引寫效能問題,我們先來看一個例子:
mysql>create table t (id int auto_increment,
name varchar(30),
primary key (id));
我們建立了一個表,表的主鍵是id,id列式自增長的,即當執行插入操作時,id列會自動增長,頁中行記錄按id順序存放,不需要隨機讀取其它頁的資料。因此,在這樣的情況下(即聚集索引),插入操作效率很高。
但是,在大部分應用中,很少出現表中只有一個聚集索引的情況,更多情況下,表上會有多個非聚集的secondary index (輔助索引)。比如,對於上一張表t,業務上還需要按非唯一的name欄位查詢,則表定義改為:
id int auto_increment,
name varchar(30),
primary key (id),
key (name));
這時,除了主鍵聚合索引外,還產生了一個name列的輔助索引,對於該非聚集索引來說,葉子節點的插入不再有序,這時就需要離散訪問非聚集索引頁,插入效能變低。
插入緩衝技術機制
為了解決這個問題,InnoDB設計出了插入緩衝技術,對於非聚集類索引的插入和更新操作,不是每一次都直接插入到索引頁中,而是先插入到記憶體中。具體做法是:如果該索引頁在緩衝池中,直接插入;否則,先將其放入插入緩衝區中,再以一定的頻率和索引頁合併,這時,就可以將同一個索引頁中的多個插入合併到一個IO操作中,大大提高寫效能。回憶一下在《這個設計思路和HBase中的LSM樹有相似之處,都是通過先在記憶體中修改,到達一定量後,再和磁碟中的資料合併,目的都是為了提高寫效能,具體可參考《HBase LSM樹》,這又再一次說明,學到最後,技術都是相通的。
插入緩衝的啟用需要滿足一下兩個條件:1)索引是輔助索引(secondary index)
2)索引不適合唯一的
如果輔助索引是唯一的,就不能使用該技術,原因很簡單,因為如果這樣做,整個索引資料被切分為2部分,無法保證唯一性。
插入緩衝帶來的問題
任何一項技術在帶來好處的同時,必然也帶來壞處。插入緩衝主要帶來如下兩個壞處:1)可能導致資料庫宕機後例項恢復時間變長。如果應用程式執行大量的插入和更新操作,且涉及非唯一的聚集索引,一旦出現宕機,這時就有大量記憶體中的插入緩衝區資料沒有合併至索引頁中,導致例項恢復時間會很長。
2)在寫密集的情況下,插入緩衝會佔用過多的緩衝池記憶體,預設情況下最大可以佔用1/2,這在實際應用中會帶來一定的問題。