世界上最快的捷徑,就是腳踏實地,本文已收錄【 架構技術專欄】關注這個喜歡分享的地方。
InnoDB引擎有幾個重點特性,爲其帶來了更好的性能和可靠性:數據庫
今天咱們的主題就是 插入緩衝(Insert Buffer)
,因爲InnoDB引擎底層數據存儲結構式B+樹,而對於索引咱們又有彙集索引和非彙集索引。數據結構
在進行數據插入時必然會引發索引的變化,彙集索引沒必要說,通常都是遞增有序的。而非彙集索引就不必定是什麼數據了,其離散性致使了在插入時結構的不斷變化,從而致使插入性能下降。架構
因此爲了解決非彙集索引插入性能的問題,InnoDB引擎 創造了Insert Buffer。異步
看到上圖,可能你們會認爲Insert Buffer 就是InnoDB 緩衝池的一個組成部分。性能
重點:其實對也不對,InnoDB 緩衝池確實包含了Insert Buffer的信息,但Insert Buffer 其實和數據頁同樣,也是物理存在的(以B+樹的形式存在共享表空間中)。優化
先說幾個點:spa
首先咱們知道在InnoDB存儲引擎中,主鍵是行惟一的標識符(也就是咱們常叨叨的彙集索引)。咱們平時插入數據通常都是按照主鍵遞增插入,所以彙集索引都是順序的,不須要磁盤的隨機讀取。線程
好比表:設計
CREATE TABLE test( id INT AUTO_INCREMENT, name VARCHAR(30), PRIMARY KEY(id) );
如上我建立了一個主鍵 id,它有如下的特性:3d
通常狀況下因爲彙集索引的有序性,不須要隨機讀取頁中的數據,由於此類的順序插入速度是很是快的。
但若是你把列 Id 插入UUID這種數據,那你插入就是和非彙集索引同樣都是隨機的了。會致使你的B+ tree結構不停地變化,那性能必然會受到影響。
不少時候咱們的表還會有不少非彙集索引,好比我按照b字段查詢,且b字段不是惟一的。以下表:
CREATE TABLE test( id INT AUTO_INCREMENT, name VARCHAR(30), PRIMARY KEY(id), KEY(name) );
這裏我建立了一個x表,它有如下特色:
非彙集索引也是一顆B+樹,只是葉子節點存的是彙集索引的主鍵和name 的值。
由於不能保證name列的數據是順序的,因此非彙集索引這棵樹的插入必然也不是順序的了。
固然若是name列插入的是時間類型數據,那其非彙集索引的插入也是順序的。
能夠看出非彙集索引插入的離散性致使了插入性能的降低,所以InnoDB引擎設計了 Insert Buffer來提升插入性能 。
我來看看使用Insert Buffer 是怎麼插入的:
首先對於非彙集索引的插入或更新操做,不是每一次直接插入到索引頁中,而是先判斷插入的非彙集索引頁是否在緩衝池中。
若在,則直接插入;若不在,則先放入到一個Insert Buffer對象中。
給外部的感受好像是樹已經插入非彙集的索引的葉子節點,而實際上是存放在其餘位置了
以必定的頻率和狀況進行Insert Buffer和輔助索引頁子節點的merge(合併)操做,一般會將多個插入操做一塊兒進行merge,這就大大的提高了非彙集索引的插入性能。
只有知足上面兩個必要條件時,InnoDB存儲引擎纔會使用Insert Buffer來提升插入性能。
那爲何必須知足上面兩個條件呢?
第一點索引是非彙集索引就不用說了,人家彙集索引原本就是順序的也不須要你
第二點必須不是惟一(unique)的,由於在寫入Insert Buffer時,數據庫並不會去判斷插入記錄的惟一性。若是再去查找確定又是離散讀取的狀況了,這樣InsertBuffer就失去了意義。
咱們可使用命令SHOW ENGINE INNODB STATUS來查看Insert Buffer的信息:
------------------------------------- INSERT BUFFER AND ADAPTIVE HASH INDEX ------------------------------------- Ibuf: size 7545, free list len 3790, seg size 11336, 8075308 inserts,7540969 merged sec, 2246304 merges ...
使用命令後,咱們會看到不少信息,這裏咱們只看下INSERT BUFFER 的:
merges:merged recs大約爲1∶3,表明了Insert Buffer 將對於非彙集索引頁的離散IO邏輯請求大約下降了2/3
說了這麼多針對於Insert Buffer的好處,但目前Insert Buffer也存在一個問題:
即在寫密集的狀況下,插入緩衝會佔用過多的緩衝池內存(innodb_buffer_pool),默認最大能夠佔用到1/2的緩衝池內存。
佔用了過大的緩衝池必然會對其餘緩衝池操做帶來影響
MySQL5.5以前的版本中其實都叫作Insert Buffer,以後優化爲 Change Buffer
能夠看作是 Insert Buffer 的升級版。
插入緩衝( Insert Buffer)這個其實只針對 INSERT 操做作了緩衝,而Change Buffer 對INSERT、DELETE、UPDATE都進行了緩衝,因此能夠統稱爲寫緩衝,其能夠分爲:
Insert Buffer究竟是個什麼?
如下幾種狀況下 Insert Buffer會寫入真正非彙集索引,也就是所說的Merge Insert Buffer
一句話歸納下:
Insert Buffer 就是用於提高非彙集索引頁的插入性能的,其數據結構相似於數據頁的一個B+樹,物理存儲在共享表空間ibdata1中 。