MySql索引機制


第一部分 MySQL數據庫索引的數據結構算法理論

第二部分 MySQL索引實現機制

第三部分 MySQL中高性能使用索引的策略

數據結構及算法

MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數據的數據結構

查詢算法的進化:

順序查找(linear search)時間復雜度為O(n)  ====》 優化查找算法(二分查找(binary search)、二叉樹查找(binary tree search)等)

問題來了:查找效率提高了,但是各自對檢索的數據都有要求:二分查找要求被檢索數據有序,而二叉樹查找只能應用於二叉查找樹上,但是數據本身的組織結構不可能完全滿足各種數據結構(例如,理論上不可能同時將兩列都按順序進行組織)

    上圖展示了一種可能的索引方式。左邊是數據表,一共有兩列七條記錄,最左邊的是數據記錄的物理地址(注意邏輯上相鄰的記錄在磁盤上也並不是一定物理相鄰的)。為了加快Col2的查找,可以維護一個右邊所示的二叉查找樹,每個節點分別包含索引鍵值和一個指向對應數據記錄物理地址的指針,這樣就可以運用二叉查找;但是 實際的數據庫系統幾乎沒有使用二叉查找樹或其進化品種紅黑樹(red-black tree)實現的,原因會在下文介紹。

B-Tree和B+Tree

目前大部分數據庫系統及文件系統都采用B-Tree或其變種B+Tree作為索引結構,在下一節會結合存儲器原理及計算機存取原理討論為什么B-Tree和B+Tree在被如此廣泛用於索引。

 

B-Tree

定義一條數據記錄為一個二元組[key, data],key為記錄的鍵值,對於不同數據記錄,key是互不相同的;data為數據記錄除key外的數據。B-Tree是滿足下列條件的數據結構:

  1. d>=2,即B-Tree的度;
  2. h為B-Tree的高;
  3. 每個非葉子結點由n-1個key和n個指針組成,其中d<=n<=2d;
  4. 每個葉子結點至少包含一個key和兩個指針,最多包含2d-1個key和2d個指針,葉結點的指針均為NULL;
  5. 所有葉結點都在同一層,深度等於樹高h;
  6. key和指針相互間隔,結點兩端是指針;
  7. 一個結點中的key從左至右非遞減排列;
  8. 如果某個指針在結點node最左邊且不為null,則其指向結點的所有key小於
  9. 如果某個指針在結點node最右邊且不為null,則其指向結點的所有key大於
  10. 如果某個指針在結點node的左右,相鄰key分別是指向節點的上下界限

如下圖是一個 d=2的B-Tree

B+Tree

B-Tree有許多變種,其中最常見的是B+Tree,例如MySQL就普遍使用B+Tree實現其索引結構

由於並不是所有節點都具有相同的域,因此B+Tree中葉結點和內結點一般大小不同。這點與B-Tree不同,雖然B-Tree中不同節點存放的key和指針可能數量不一致,但是每個結點的域和上限是一致的,所以在實現中B-Tree往往對每個結點申請同等大小的空間。

B+Tree比B-Tree更適合實現外存儲索引結構,具體原因與外存儲器原理及計算機存取原理有關。

參照:https://www.cnblogs.com/dongguacai/p/7239599.html

 

B-/+Tree索引的性能分析

從使用磁盤I/O次數評價索引結構的優劣性:根據B-Tree的定義,可知檢索一次最多需要訪問h個結點。數據庫系統的設計者巧妙的利用了磁盤預讀原理,將一個結點的大小設為等於一個頁面,這樣每個結點只需要一次I/O就可以完全載入。為了達到這個目的,在實際實現B-Tree還需要使用如下技巧:

每次新建結點時,直接申請一個頁面的空間,這樣可以保證一個結點的大小等於一個頁面,加之計算機存儲分配都是按頁對齊的,就實現了一個node只需一次I/O。

B-Tree中一次檢索最多需要h-1次I/O(根結點常駐內存),漸進復雜度為O(h)=O(logdN)。一般實際應用中,出讀d是非常大的數字,通常超過100,因此h非常小。

綜上所述,用B-Tree作為索引結構效率是非常高的。

而紅黑樹結構,h明顯要深得多。由於邏輯上很近的結點(父子結點)物理上可能離得很遠,無法利用局部性原理。所以即使紅黑樹的I/O漸進復雜度也為O(h),但是查找效率明顯比B-Tree差得多。

MySQL索引實現

MyIASM引擎的索引結構

   前面已經說過,索引存儲的是[key, value],key是建立索引的數據列,value是存儲的數據域。MyIASM引擎的數據域內容是數據實際物理地址,這種與實際數據分離的索引即是 非聚集索引。 

       

    上圖中數據表一共有三列,Col1為主鍵,則上圖是一個MyISAM表的主索引(Primary key)示意圖。在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重復。

   MyISAM中索引檢索的算法為首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然后以data域的值為地址,讀取相應數據記錄。

InnoDB引擎的索引結構

   InnoDB引擎的[key, value]中,value存儲的是實際數據,這種索引也叫聚集索引。

  如下圖所示, 表數據文件本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。

   

       InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作為主鍵,如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含字段作為主鍵。

      與MyISAM索引的不同是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域。如下圖所示:

 

     這里以英文字符的ASCII碼作為比較准則。聚集索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄

     

     

   

 

 

 

 

 

 


免責聲明!

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



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