Mysql索引的理解:B-Tree(B-樹)和B+Tree(B+樹)
為什麼會使用B-Tree和B+Tree,而不是二叉樹、紅黑樹
資料結構
說索引之前需要先提到一點,樹結構做查詢時,最壞情況需要查詢的次數是樹的高度H,而對於Mysql來說,當資料檔案很大時,就需要根據樹的節點把對應的資料載入到記憶體中,也就是I/O。
上面的描述中有幾點資訊:
- 樹高H影響查詢次數;
- 上一點中的每一次查詢還會涉及到磁碟I/O;
。
d 為內節點出度,表示非根節點和葉子節點擁有最少的子女數,並且規定最大不能超過 2d。
注意:這裡也有文獻會反過來表示,即最大為 d, 最少不能少於
很明顯,樹高度H越高查詢效率越低。
回到問題上,我相信很多人已經猜到了為什麼B樹會比二叉樹更合理了!但是這只是說明了一個層面的東西,高度越低查詢次數越少。
區域性性原理與磁碟預讀
由於儲存介質的特性,磁碟本身存取就比主存慢很多,再加上機械運動耗費,磁碟的存取速度往往是主存的幾百分分之一,因此為了提高效率,要儘量減少磁碟I/O。為了達到這個目的,磁碟往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個位元組,磁碟也會從這個位置開始,順序向後讀取一定長度的資料放入記憶體。這樣做的理論依據是電腦科學中著名的區域性性原理:當一個數據被用到時,其附近的資料也通常會馬上被使用。 由於磁碟順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對於具有區域性性的程式來說,預讀可以提高I/O效率。
資料庫系統的設計者巧妙利用了磁碟預讀原理 ,將一個節點的大小設為等於一個頁,這樣每個節點只需要一次I/O就可以完全載入。為了達到這個目的,在實際實現B-Tree還需要使用如下技巧:
每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也儲存在一個頁裡,加之計算機儲存分配都是按頁對齊的,就實現了一個node只需一次I/O。
B-Tree 和 B+Tree 區別
最大上的不同是內節點不儲存資料。
另外,每個節點的指標數不一樣,B-Tree 是資料隔開指標 ,上文提到過最大子女數是 2d,所以B-Tree的最大指標數是 2d+1;而B+Tree 是 2d。
Mysql不同索引實現
通過上文兩點,我們理解了為什麼使用B樹。但同樣是B樹,也有不同的使用。
聚集和非聚集
聚集與非聚集的主要區別可理解為索引的葉子節點中儲存是真實的資料還只是指標。這一點,在MyISAM和InnoDB的主鍵之間表現是不同的。MyISAM使用的是非聚集,最好的表現在MyISAM的儲存檔案分為索引檔案(.MYI)和資料檔案(.MYD),而InnoDB是索引和資料在一個檔案裡。
上文可理解MyISAM和InnoDB區別之:
- 儲存的檔案內容不一樣;
- 因為InnoDB是根據主鍵聚集資料的,所以在建立InnoDB表時必需要有主鍵 ;
- 擴充套件一點:InnoDB輔助索引是根據主鍵值聚集的 ;什麼意思?就是InnoDB的非主鍵索引的葉子節點裡儲存的是主鍵的值;
參考資料
- ofollow,noindex">MySQL索引背後的資料結構及演算法原理
- 為什麼 B-tree 在不同著作中度的定義有一定差別