java面試題:你了解mysql的B+TREE索引嗎?


  • 什么是索引?

  索引是為了加速對表中數據行的檢索而創建的一種分散儲存的數據結構。

  工作原理:

  

  通過我們建立的索引,可以通過命中后的磁盤地址快速的找到我們需要的表數據,比起全表掃描去查詢數據,可以大大的提升查找效率。

  在關系型數據庫中,索引是硬盤級索引。

  • 常見的數據結構

  1)二叉樹

  

  二叉樹相信大家都非常熟悉,以一個節點為根節點,比該節點小的值走左邊,大的值走右邊。搜索數據時,只要通過它的數據鏈接就可找到相應的數據。右邊為一個節點里的具體組成部分。

  缺點:二叉樹有個極其致命的缺點,當插入數據為順序遞增或順序遞減時,形成的二叉樹就成了單邊鏈條。

  

  這樣的話,查找也沒有效率可言。

  2)平衡二叉查找樹

  平衡二叉查找樹作為二叉查找樹的進階版,改進了二叉查找樹的缺點。

  定義:它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。

  即,當平衡二叉查找樹數據插入時,如果發現形成的樹結構違反了它的定義,那么此時樹會發生形變,組成一顆相對平衡的查找樹。

  如果還是以上面的1-5順序插入時,形成的樹結構為

  

  紅黑樹也是平衡二叉查找樹的一種實現。

  因此不建議對數據頻繁變更的列建立索引,因為在這個過程中,索引的結構變更必然會帶來IO流和CPU的損耗。

  缺點:

    1.搜索效率不足。

      因為歸根結底還是二叉樹結構,因此在數據量大的時候,樹的高度極高,也就意味着可能一次查找需要超多次數的IO。

    2.節點數據內容太少。

      每一個節點中保存的數據遠遠不夠填滿一次內存和磁盤交互的值。如果一次內存和磁盤的交互為4KB,那么一個節點中保存的數據其實就大大浪費了這個空間。

  3)B tree(多路平衡查找樹,絕對平衡)

  

  那么B樹如何解決平衡二叉樹的缺點呢?

  上圖是一個三路平衡查找樹,因為Btree是多路平衡查找樹的原因,它可以是三路,四路,五路六路,路越多,就意味着樹的高度越低,那么一次搜索的最大IO次數也就越少。

  也因為它的多路特性,一次IO交互的磁盤塊中可能保存着巨大數量的節點數據。我們以id為int為例,一次IO交互假設為4KB,那么一次IO交互最多能保存1024個關鍵字!(當然一個節點中有數據區和子節點引用,粗略計算)。

  因此我們在設置數據庫的字段類型和字段長度的時候,控制字段類型合理,字段長度合理,就能保證每次索引磁盤塊的加載能包含更多數據,從而提升我們的查找效率。

  4)B+tree(加強版多路絕對平衡查找樹)

  我們還是以三路查找樹為例

  

  B+樹的特點:

  1. 非葉節點不保存數據相關信息,只保存關鍵字和子節點的引用。
  2. 所有的數據都保存的葉子節點中。
  3. 采用左閉合區間。
  4. 葉子節點中的數據順序排列,並且相鄰節點具有順序引用的關系。  

  B+樹相比B樹的優點:

  1. 掃庫、掃表能力更強
  2. 磁盤讀寫能力更強(因為少保存了個數據區)
  3. 排序能力更強
  4. 查找效率更加穩定(B樹可能一次命中,也可能多次命中,而B+樹因為沒有保存數據區的緣故,樹的高度相對更低,但每次都要查找到最多次數)
  • mysql中B+tree的具體落地形式
  1. myisam

    myisam存儲引擎的表會有三個文件   

      .frm文件存儲表定義;
      ·MYD (MYData)文件存儲表的數據;
      .MYI (MYIndex)文件存儲表的索引。
    myisam中的索引結構為平級結構,即id或name索引都會獨立指向數據地址值。
    
  1. innodb

    innodb存儲引擎的表有兩個文件

      .frm文件儲存表定義;

      .ibd儲存索引和數據。

    innodb是一個以主鍵為索引來組織數據的存儲引擎,主鍵索引形成數據結構,具體的數據值保存在葉子節點,而輔助索引中的葉子節點保存了指向主文件的主鍵關鍵字。如果沒有指定主鍵,innodb會生成隱藏的6位自增列rowid。

    

  • 索引的幾大原則
  1. 最左匹配原則

    對索引中關鍵字進行計算和比對,一定是從左往右一次執行,且不可跳過。

  1. 高離散度原則

    列中的數據重復率越低,離散度越好。

  1. 最少空間原則

    索引的創建原則為 最左匹配 > 高離散度 > 最少空間。

  1. 聯合索引和覆蓋索引
    1. 聯合索引

        單列索引是特殊的聯合索引,如果建立的聯合索引中包含了單列索引及小於該范圍的聯合索引,要注意索引的冗余。(例如:index[id,name]>index[name])

    1. 覆蓋索引

        如果查詢的列,通過索引項的信息可以直接返回,則該索引為覆蓋索引。

        例:table(teacher)index(id)

        sql:select id from teacher where id = ?

        

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM