MySQL中的索引 B+Tree

MySQL中的索引 B+Tree

1. 常見索引的數據結構

示意圖均從www.cs.usfca.edu生成

  • 哈希(Hash)
    • 示意圖
      Hash示意圖
    • 效率高,但是因爲Hash算法的特性,數據無序,不能進行範圍搜索
    • MySQL支持Hash索引
  • 二分搜索樹(Binary Search Tree)
    • 示意圖
      二分搜索樹示意圖
    • 數據有序,能夠按範圍查找,但是容易造成部分數據傾斜,導致該部分數據查詢較慢
  • 平衡二分搜索樹(Balanced Binary Search Tree, AVL Tree)
    • 示意圖
      平衡二分搜索樹示意圖
    • 是二分搜索樹的優化版,解決了數據傾斜的問題,但是需要維護樹平衡的額外開銷
  • B樹(B Tree)
    • 示意圖
      B樹示意圖
    • 每個節點可以存多條數據,子節點數量也可以大於2,優化了樹的深度
  • B+樹(B+Tree)
    • 示意圖
      B+樹示意圖
    • 葉子節點會額外存儲指向相鄰葉子節點的指針,優化B樹範圍查詢效率,且更加穩定
    • 最底層存實際的數據(只有葉子節點存數據)
  • B*樹
    • 是B+樹的變體,在B+樹的非根、非葉子節點再增加指向兄弟節點的指針

2. MySQL中B+Tree的使用

  • MySQL中索引主要採用B+Tree(Memory引擎採用Hash索引),其關鍵點如下:
    • 非葉子節點存索引,控制樹的深度
    • 葉子節點存數據,以及指向相鄰葉子節點的指針
    • 數據存入硬盤,需控制每一份數據的大小,以適應硬盤分頁
  • 那麼每一份數據應該存多大呢?
    • MySQL每一份數據是硬盤分頁大小的倍數
      • 系統從硬盤中進行讀取操作,是按頁讀取的
      • 如果MySQL每一份數據的大小比硬盤一頁的量小,那麼每次硬盤讀取就可能會讀取一些不需要的數據,影響性能
    • 通過 SHOW GLOBAL STATUS LIKE 'Innodb_page_size';即可查看MySQL每份數據的大小
    • MySQL-5.7中Innodb_page_size=16kb

3. MySQL中兩大主要引擎的索引

  • MyISAM(非聚集索引)
    • 索引(*.MYI)和數據(*.MYD)分開存
      • *.MYI文件中B+Tree的葉子節點存儲數據地址,地址對應*.MYD中的數據
    • 主鍵索引(Primary Key): 直接根據索引找到值
    • 輔助索引(Secondary Key): 直接根據索引找到值
    • 其他
      • 支持表鎖
      • 不支持外鍵
      • 不支持事務
      • 不支持全文索引
  • InnoDB(聚集索引)
    • 索引和數據存一起(*.ibd)
      • 必須有一個索引,沒有會建一個默認的長整型索引(一般推薦設置一個整型自增主鍵,隨機主鍵會導致B+Tree頻繁分裂)
      • *.ibd文件中包含B+Tree索引,以及具體的數據(存在B+Tree的葉子節點)
    • 主鍵索引(Primary Key): 直接根據索引找到值
    • 輔助索引(Secondary Key): 先用索引找到主鍵,再根據主鍵找到值
    • 其他
      • 支持表鎖、行鎖
      • 支持外鍵
      • 事務安全
      • 支持全文索引

4. 適合創建索引的字段

  • 主鍵自動創建索引(推薦自增整型主鍵)
  • 頻繁作爲查詢條件的字段
  • 經常與其他表關聯的字段
  • 經常用作統計、聚合分析的字段
  • 經常用作排序的字段
  • 單鍵/組合索引,滿足業務條件下,優先選擇組合索引(最左前綴原則)
  • 注意點
    • 使用索引時,應遵守最左前綴原則
    • 不要在索引列上做任何操作(計算、函數等等),否則會導致索引失效
    • !=、<>、IS NULL、IS NOT NULL會導致索引列失效
    • 關於like查詢,LIKE '%word%'會可能導致索引列失效,LIKE 'word%'仍能使用索引
    • 如果where中存在範圍條件,那麼該條件右邊的列的索引會失效
    • 儘量使用覆蓋索引(只訪問索引)
    • OR可能會導致索引失效
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章