1. 程式人生 > >MySQL之InnoDB索引面試學習筆記

MySQL之InnoDB索引面試學習筆記

family 技術分享 ron myisam 不同 索引數據 想要 math 減少

寫在前面

  想要做好後臺開發,終究是繞不過索引這一關的。先問自己一個問題,InnoDB為什麽選擇B+樹作為默認索引結構。本文主要參考MySQL索引背後的數據結構及算法原理和剖析Mysql的InnoDB索引。

索引

  當數據量到達一定規模時,我們通常會對經常使用的字段建立索引,來加快數據的查詢。首先需要強調的是索引的本質是數據結構,前輩們經過不斷完善得到了幾種復雜度較低並且能夠降低磁盤IO的數據結構,這裏要說的是B樹與B+樹,他們被廣泛應用在文件系統與數據庫系統中。

B-Tree

  B樹邏輯上是一顆多叉樹,3階B樹如下:

技術分享圖片

  m階B樹滿足以下幾個條件:

  • 非葉子節點最少有m/2顆子樹
  • 葉子節點在同一層,每個節點最多有m-1個升序排列的key(索引列)和m個指針,key與指針相互間隔

搜索二叉樹的查詢復雜度為O(log2N),而B樹的復雜度為O(logm/2N),對於N=62*1000000000個節點,如果度為1024,則logM/2N <=4,可以說它是效率很高的數據結構。

B+樹

  B+樹是B樹的變種,區別有三點:

  • 非葉子節點只存儲key,不存儲data;葉子節點存儲所有key與data,不存儲指針
  • 葉子節點增加了順序訪問指針
  • 每個節點最多有m個升序排列的key  

技術分享圖片

  上述區別換來的優點包括:

  • 非子節點可以存放更多的key,具有更好的空間局部性,提高緩存命中率
  • 葉子節點相鏈便於區間查找,順序查找替代B樹的遞歸查找。

為什麽選擇B+樹

  首先要意識到數據檢索的時間主要耗費在磁盤IO(尋道時間、旋轉時間)上,因此要盡量減少IO次數。對樹形結構的數據來說,樹的每一層代表需要一次磁盤IO查詢,因此設計了“扁平”的B樹與更扁的B+樹。另外,由著名的局部性原理,訪問的數據通常比較集中,磁盤每次IO時會預讀數據,預讀的長度為頁(4k)的整數倍,B/B+樹新建節點會申請一個頁的空間,因此取一個節點只需要一次IO

(非葉子節點可存儲到內存中)。

技術分享圖片

MySQL存儲引擎

首先區分聚簇索引(按主鍵聚集)與非聚簇索引:

技術分享圖片

  • 二者使用B+樹作為數據結構
  • 聚簇索引的data存於主鍵索引的葉子節點中,得到key同時得到data,非聚簇索引數據存於獨立的地方,葉節點保存的是數據的地址
  • 聚簇索引的輔助鍵索引(非主鍵索引,例如employee表中對name建索引)葉節點存儲主鍵而非數據(為了節省空間,缺陷是需要到主鍵索引中二次查詢);非聚簇索引葉節點保存數據的地址。

  聚簇索引的優勢在於找到主鍵同時得到data,省去二次磁盤IO;另外B+樹在插入或刪除節點時周圍節點地址會發生變化,對非聚簇索引來說需要更新所有B+樹的地址指針,增加開銷。

InnoDB

  InnoDB使用聚簇索引(MyISAM使用非聚簇索引),其磁盤管理邏輯單位是Page(不同於上述內存中的頁!),每個Page大小為16k,使用32位int標識,對應innoDB最大64TB的存儲容量。

  每個Page包括頭部、主體、尾部三部分:

技術分享圖片

  其中頭部包括id與相鄰Page指針(構成雙向鏈表);

  主體即B+樹節點的存儲,其中包括很多Record(節點)包括四類:

  • 主索引非葉子節點:定位Page
  • 主索引葉子節點:包括key與該key對應的所有列(mysql表中的一行)
  • 輔助索引非葉子節點:定位Page
  • 輔助索引葉子節點:包括索引鍵值與主鍵值(key)

  

 主鍵選擇

  因為數據存於主索引中,要求一個節點的各條數據記錄按主鍵順序存放,當一頁達到裝載因子(15/16)會自動開辟新的頁。如果使用自增主鍵,每次插入新紀錄都順序添加到索引節點的後續位置,否則會節點中key會一直移動。

技術分享圖片

MySQL之InnoDB索引面試學習筆記