Mysql 學習筆記:InnoDB 索引結構淺析

索引是檢索圖書資料的一種工具,把書刊中的內容或項目分類摘錄,註明頁數,按必定次序排列。

針對不一樣的數據存儲結構有不一樣的數據查找方式。mysql

1. 數據結構

1.1 B樹

B樹又名平衡多路查找樹,主要用於文件系統中,在B樹中,每一個結點的大小爲一個磁盤頁,結點中所包含的關鍵字及其孩子的數目取決於頁的大小。算法

image

對於一顆度爲m的B樹,須要知足:sql

  1. 根結點或葉子結點,至少有2顆子樹,至多有m顆。
  2. 非葉子結點至少有 m/2顆子樹,至多有m顆。
  3. 全部葉子結點都在同一層。
  4. 每一個結點都要包含(n,Ao,K1,A1,K2,A2,K3,A3,Kn,An)緩存

    1. n是結點中關鍵字的個數,且 (m/2)-1 ≤ n ≤m-1,n+1爲子樹的棵數
    2. Ai(i=0,1,…,n)爲指向孩子結點的指針,且Ai-1所指向的子樹中全部結點的關鍵字都小於Ki ,Ai所指向的子樹中全部結點的關鍵字都大於Ki
    3. Ki(1≤i≤n)是關鍵字,且Ki<Ki+1 (1≤i≤n-1)

B樹使用二分查找,包含兩個基本操做:數據結構

  1. 在B樹上查找結點:遍歷整個樹。
  2. 在結點中查找關鍵字:每一個結點中包含m個關鍵字,經過二分查找查詢目標關鍵字。

B樹上關鍵字的增長和刪除經過平衡算法達到平衡。函數

1.2 B+樹

B+樹是B樹的變體,在實際的文件系統中基本上不使用B樹。B+樹和B樹的差別點工具

  1. 若一個結點有n棵子樹,則必含有n個關鍵字;
  2. 全部葉子結點中包含了所有記錄的關鍵字信息以及這些關鍵字記錄的指針,並且葉子結點按關鍵字的大小從小到大順序連接;
  3. 全部的非葉子結點能夠當作是索引的部分,結點中只含有其子樹的根結點中的最大(或最小)關鍵字

image

B+樹的非葉子結點不保存數據記錄的指針信息,這意味着深度相同時B+樹比B樹的關鍵字更多。性能

2.InnoDB索引類型

2.1 B+樹索引

InnoDB中的主鍵索引和輔助索引都是採用B+樹。spa

image

B樹的每一個結點大小和磁盤頁一致,磁盤每一個頁有4k,根據這個咱們就能夠計算出索引的深度。假設是一顆徹底的m階B+樹,m的大小取決於非葉子結點存儲關鍵字的數量,主鍵通常都是BIGINT 佔8個字節,那麼m=4*1024/8=512。.net

image

輔助索引的關鍵字按索引建立時定義列的順序來的,如:status + create_time,10 2020-8-1

image

B+樹結點中的關鍵字都是按順序組織的,因此關鍵字的長度和類型決定了索引的性能:

  1. 關鍵字越短,B+樹的結點就越多,樹的深度也會在預期內。
  2. 關鍵字值分佈的越均勻(重複少),B+樹就越平衡。
  3. 數字比字符串要快,由於字符串須要先作轉換再作排序:字符串排序算法。

在某些特殊場景關鍵字的值不須要均勻,如:status字段有 一、2這兩個值,1 -> 100條數據,2 -> 100萬條數據,業務上只須要查詢status爲1的記錄就會很是快,不然須要掃全表。

瞭解InnoDB索引的查找方法有助於咱們建立高效的索引:

  1. 全值匹配:比較完整的關鍵字。
  2. 匹配最左前綴:只和索引定義的第一列進行匹配。
  3. 匹配列前綴:只匹配第一列而且匹配關鍵字的前綴而非全值匹配。
  4. 匹配範圍值:匹配兩個關鍵字之間的值。(在B樹中關鍵字是順序組織的,只要查詢到當前關鍵字的父結點就能直接確認範圍)
  5. 只訪問索引:不會查詢數據行,像count這種操做就不須要再去查具體的行。

2.2 哈希索引

InnoDB中的哈希函數使用除留餘數法,衝突採用鏈地址法。

2.3 自適應哈希索引

哈希是一種很是快的查找方法,時間複雜度爲O(1),即只須要查詢一次就能定位數據,而B+樹的查找次數取決於樹的高度。InnoDB存儲引擎會監控對錶上各索引頁的查詢。若是觀察到創建哈希 索引能夠帶來速度提高,則創建哈希索引,稱之爲自適應哈希索引 (Adaptive Hash Index,AHI)。AHI是經過緩衝池的B+樹頁構造而來,所以創建的速度很快,並且不須要對整張表構建哈希索引InnoDB存儲引擎會自動根據訪問的頻率和模式來自動地爲某些熱點頁 創建哈希索引

AHI有一個要求,即對這個頁的連續訪問模式必須是同樣的。例如對 於(a,b)這樣的聯合索引頁,其訪問模式能夠是如下狀況。

模式:

  • WHERE a=xxx
  • WHERE a=xxx and b=xxx

條件:

  • 以該模式訪問了100次
  • 頁經過該模式訪問了N次,其中N=頁中記錄*1/16

自適應hash索引是mysql的功能,開發者並不能控制,儘管如此仍是要儘量的利用,若是性能沒法知足再選擇緩存中間件。


參考:

相關文章
相關標籤/搜索