<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          阿里面試官:為什么MySQL數(shù)據(jù)庫索引選擇使用B+樹而不是跳表?

          共 5306字,需瀏覽 11分鐘

           ·

          2021-11-08 14:28

          點擊關(guān)注公眾號,回復“2T”獲取2TB學習資源!
          互聯(lián)網(wǎng)架構(gòu)師后臺回復 2T 有特別禮包

          來源:https://www.cnblogs.com/andydao/p/12891690.html

          上一篇:清華大學:2021 元宇宙研究報告!
          在進一步分析為什么MySQL數(shù)據(jù)庫索引選擇使用B+樹之前,我相信很多小伙伴對數(shù)據(jù)結(jié)構(gòu)中的樹還是有些許模糊的,因此我們由淺入深一步步探討樹的演進過程,在一步步引出B樹以及為什么MySQL數(shù)據(jù)庫索引選擇使用B+樹!

          學過數(shù)據(jù)結(jié)構(gòu)的一般對最基礎(chǔ)的樹都有所認識,因此我們就從與我們主題更為相近的二叉查找樹開始。


          二叉查找樹


          (1)二叉樹簡介:


          二叉查找樹也稱為有序二叉查找樹,滿足二叉查找樹的一般性質(zhì),是指一棵空樹具有如下性質(zhì):


          1、任意節(jié)點左子樹不為空,則左子樹的值均小于根節(jié)點的值;

          2、任意節(jié)點右子樹不為空,則右子樹的值均大于于根節(jié)點的值;

          3、任意節(jié)點的左右子樹也分別是二叉查找樹;

          4、沒有鍵值相等的節(jié)點; 

           

          上圖為一個普通的二叉查找樹,按照中序遍歷的方式可以從小到大的順序排序輸出:2、3、5、6、7、8。

          對上述二叉樹進行查找,如查鍵值為5的記錄,先找到根,其鍵值是6,6大于5,因此查找6的左子樹,找到3;而5大于3,再找其右子樹;一共找了3次。如果按2、3、5、6、7、8的順序來找同樣需求3次。用同樣的方法在查找鍵值為8的這個記錄,這次用了3次查找,而順序查找需要6次。計算平均查找次數(shù)得:順序查找的平均查找次數(shù)為(1+2+3+4+5+6)/ 6 = 3.3次,二叉查找樹的平均查找次數(shù)為(3+3+3+2+2+1)/6=2.3次。二叉查找樹的平均查找速度比順序查找來得更快。


          (2)局限性及應用


          一個二叉查找樹是由n個節(jié)點隨機構(gòu)成,所以,對于某些情況,二叉查找樹會退化成一個有n個節(jié)點的線性鏈。如下圖: 

           
          大家看上圖,如果我們的根節(jié)點選擇是最小或者最大的數(shù),那么二叉查找樹就完全退化成了線性結(jié)構(gòu)。上圖中的平均查找次數(shù)為(1+2+3+4+5+5)/6=3.16次,和順序查找差不多。顯然這個二叉樹的查詢效率就很低,因此若想最大性能的構(gòu)造一個二叉查找樹,需要這個二叉樹是平衡的(這里的平衡從一個顯著的特點可以看出這一棵樹的高度比上一個輸?shù)母叨纫?,在相同?jié)點的情況下也就是不平衡),從而引出了一個新的定義-平衡二叉樹AVL。


          AVL樹


          (1)簡介


          AVL樹是帶有平衡條件的二叉查找樹,一般是用平衡因子差值判斷是否平衡并通過旋轉(zhuǎn)來實現(xiàn)平衡,左右子樹樹高不超過1,和紅黑樹相比,它是嚴格的平衡二叉樹,平衡條件必須滿足(所有節(jié)點的左右子樹高度差不超過1)。不管我們是執(zhí)行插入還是刪除操作,只要不滿足上面的條件,就要通過旋轉(zhuǎn)來保持平衡,而旋轉(zhuǎn)是非常耗時的,由此我們可以知道AVL樹適合用于插入刪除次數(shù)比較少,但查找多的情況。 

           
          從上面是一個普通的平衡二叉樹,這張圖我們可以看出,任意節(jié)點的左右子樹的平衡因子差值都不會大于1。


          (2)局限性


          由于維護這種高度平衡所付出的代價比從中獲得的效率收益還大,故而實際的應用不多,更多的地方是用追求局部而不是非常嚴格整體平衡的紅黑樹。當然,如果應用場景中對插入刪除不頻繁,只是對查找要求較高,那么AVL還是較優(yōu)于紅黑樹。


          (3)應用


          1、Windows NT內(nèi)核中廣泛存在;


          紅黑樹


          (1)簡介


          一種二叉查找樹,但在每個節(jié)點增加一個存儲位表示節(jié)點的顏色,可以是red或black。通過對任何一條從根到葉子的路徑上各個節(jié)點著色的方式的限制,紅黑樹確保沒有一條路徑會比其它路徑長出兩倍。它是一種弱平衡二叉樹(由于是若平衡,可以推出,相同的節(jié)點情況下,AVL樹的高度低于紅黑樹),相對于要求嚴格的AVL樹來說,它的旋轉(zhuǎn)次數(shù)變少,所以對于搜索、插入、刪除操作多的情況下,我們就用紅黑樹。


          (2)性質(zhì)


          1、每個節(jié)點非紅即黑; 
          2、根節(jié)點是黑的; 
          3、每個葉節(jié)點(葉節(jié)點即樹尾端NULL指針或NULL節(jié)點)都是黑的; 
          4、如果一個節(jié)點是紅的,那么它的兩兒子都是黑的; 
          5、對于任意節(jié)點而言,其到葉子點樹NULL指針的每條路徑都包含相同數(shù)目的黑節(jié)點; 
          6、每條路徑都包含相同的黑節(jié)點;

          (3)應用


          1、廣泛用于C++的STL中,Map和Set都是用紅黑樹實現(xiàn)的; 
          2、著名的Linux進程調(diào)度Completely Fair Scheduler,用紅黑樹管理進程控制塊,進程的虛擬內(nèi)存區(qū)域都存儲在一顆紅黑樹上,每個虛擬地址區(qū)域都對應紅黑樹的一個節(jié)點,左指針指向相鄰的地址虛擬存儲區(qū)域,右指針指向相鄰的高地址虛擬地址空間; 
          3、IO多路復用epoll的實現(xiàn)采用紅黑樹組織管理sockfd,以支持快速的增刪改查; 
          4、Nginx中用紅黑樹管理timer,因為紅黑樹是有序的,可以很快的得到距離當前最小的定時器; 
          5、Java中TreeMap的實現(xiàn);


          B/B+樹


          說了上述的三種樹:二叉查找樹、AVL和紅黑樹,似乎我們還沒有摸到MySQL為什么要使用B+樹作為索引的實現(xiàn),不要急,接下來我們就先探討一下什么是B樹。


          (1)簡介


          我們在MySQL中的數(shù)據(jù)一般是放在磁盤中的,讀取數(shù)據(jù)的時候肯定會有訪問磁盤的操作,磁盤中有兩個機械運動的部分,分別是盤片旋轉(zhuǎn)和磁臂移動。盤片旋轉(zhuǎn)就是我們市面上所提到的多少轉(zhuǎn)每分鐘,而磁盤移動則是在盤片旋轉(zhuǎn)到指定位置以后,移動磁臂后開始進行數(shù)據(jù)的讀寫。那么這就存在一個定位到磁盤中的塊的過程,而定位是磁盤的存取中花費時間比較大的一塊,畢竟機械運動花費的時候要遠遠大于電子運動的時間。當大規(guī)模數(shù)據(jù)存儲到磁盤中的時候,顯然定位是一個非?;ㄙM時間的過程,但是我們可以通過B樹進行優(yōu)化,提高磁盤讀取時定位的效率。

          為什么B類樹可以進行優(yōu)化呢?我們可以根據(jù)B類樹的特點,構(gòu)造一個多階的B類樹,然后在盡量多的在結(jié)點上存儲相關(guān)的信息,保證層數(shù)盡量的少,以便后面我們可以更快的找到信息,磁盤的I/O操作也少一些,而且B類樹是平衡樹,每個結(jié)點到葉子結(jié)點的高度都是相同,這也保證了每個查詢是穩(wěn)定的。

          總的來說,B/B+樹是為了磁盤或其它存儲設(shè)備而設(shè)計的一種平衡多路查找樹(相對于二叉,B樹每個內(nèi)節(jié)點有多個分支),與紅黑樹相比,在相同的的節(jié)點的情況下,一顆B/B+樹的高度遠遠小于紅黑樹的高度(在下面B/B+樹的性能分析中會提到)。

          B/B+樹上操作的時間通常由存取磁盤的時間和CPU計算時間這兩部分構(gòu)成,而CPU的速度非常快,所以B樹的操作效率取決于訪問磁盤的次數(shù),關(guān)鍵字總數(shù)相同的情況下B樹的高度越小,磁盤I/O所花的時間越少。

          注意B-樹就是B樹,-只是一個符號。


          (2)B樹的性質(zhì)


          1、定義任意非葉子結(jié)點最多只有M個兒子,且M>2; 
          2、根結(jié)點的兒子數(shù)為[2, M]; 
          3、除根結(jié)點以外的非葉子結(jié)點的兒子數(shù)為[M/2, M]; 
          4、每個結(jié)點存放至少M/2-1(取上整)和至多M-1個關(guān)鍵字;(至少2個關(guān)鍵字) 
          5、非葉子結(jié)點的關(guān)鍵字個數(shù)=指向兒子的指針個數(shù)-1; 
          6、非葉子結(jié)點的關(guān)鍵字:K[1], K[2], …, K[M-1];且K[i] < K[i+1]; 
          7、非葉子結(jié)點的指針:P[1], P[2], …, P[M];其中P[1]指向關(guān)鍵字小于K[1]的子樹,P[M]指向關(guān)鍵字大于K[M-1]的子樹,其它P[i]指向關(guān)鍵字屬于(K[i-1], K[i])的子樹; 
          8、所有葉子結(jié)點位于同一層; 




          這里只是一個簡單的B樹,在實際中B樹節(jié)點中關(guān)鍵字很多的,上面的圖中比如35節(jié)點,35代表一個key(索引),而小黑塊代表的是這個key所指向的內(nèi)容在內(nèi)存中實際的存儲位置,是一個指針。


          B+樹


          (1)簡介


          B+樹是應文件系統(tǒng)所需而產(chǎn)生的一種B樹的變形樹(文件的目錄一級一級索引,只有最底層的葉子節(jié)點(文件)保存數(shù)據(jù))非葉子節(jié)點只保存索引,不保存實際的數(shù)據(jù),數(shù)據(jù)都保存在葉子節(jié)點中,這不就是文件系統(tǒng)文件的查找嗎?


          我們就舉個文件查找的例子:有3個文件夾a、b、c, a包含b,b包含c,一個文件yang.c,a、b、c就是索引(存儲在非葉子節(jié)點), a、b、c只是要找到的yang.c的key,而實際的數(shù)據(jù)yang.c存儲在葉子節(jié)點上。


          所有的非葉子節(jié)點都可以看成索引部分!


          (2)B+樹的性質(zhì)(下面提到的都是和B樹不相同的性質(zhì))


          1、非葉子節(jié)點的子樹指針與關(guān)鍵字個數(shù)相同; 
          2、非葉子節(jié)點的子樹指針p[i],指向關(guān)鍵字值屬于[k[i],k[i+1]]的子樹.(B樹是開區(qū)間,也就是說B樹不允許關(guān)鍵字重復,B+樹允許重復); 
          3、為所有葉子節(jié)點增加一個鏈指針; 
          4、所有關(guān)鍵字都在葉子節(jié)點出現(xiàn)(稠密索引). (且鏈表中的關(guān)鍵字恰好是有序的); 
          5、非葉子節(jié)點相當于是葉子節(jié)點的索引(稀疏索引),葉子節(jié)點相當于是存儲(關(guān)鍵字)數(shù)據(jù)的數(shù)據(jù)層; 
          6、更適合于文件系統(tǒng);

          非葉子節(jié)點(比如5,28,65)只是一個key(索引),實際的數(shù)據(jù)存在葉子節(jié)點上(5,8,9)才是真正的數(shù)據(jù)或指向真實數(shù)據(jù)的指針。


          (3)應用  


          1、B和B+樹主要用在文件系統(tǒng)以及數(shù)據(jù)庫做索引,比如MySQL;


          B/B+樹性能分析


          n個節(jié)點的平衡二叉樹的高度為H(即logn),而n個節(jié)點的B/B+樹的高度為logt((n+1)/2)+1; 


          若要作為內(nèi)存中的查找表,B樹卻不一定比平衡二叉樹好,尤其當m較大時更是如此。因為查找操作CPU的時間在B-樹上是O(mlogtn)=O(lgn(m/lgt)),而m/lgt>1;所以m較大時O(mlogtn)比平衡二叉樹的操作時間大得多。因此在內(nèi)存中使用B樹必須取較小的m。(通常取最小值m=3,此時B-樹中每個內(nèi)部結(jié)點可以有2或3個孩子,這種3階的B-樹稱為2-3樹)。


          為什么說B+樹比B樹更適合數(shù)據(jù)庫索引?


          1、 B+樹的磁盤讀寫代價更低:B+樹的內(nèi)部節(jié)點并沒有指向關(guān)鍵字具體信息的指針,因此其內(nèi)部節(jié)點相對B樹更小,如果把所有同一內(nèi)部節(jié)點的關(guān)鍵字存放在同一盤塊中,那么盤塊所能容納的關(guān)鍵字數(shù)量也越多,一次性讀入內(nèi)存的需要查找的關(guān)鍵字也就越多,相對IO讀寫次數(shù)就降低了。


          2、B+樹的查詢效率更加穩(wěn)定:由于非終結(jié)點并不是最終指向文件內(nèi)容的結(jié)點,而只是葉子結(jié)點中關(guān)鍵字的索引。所以任何關(guān)鍵字的查找必須走一條從根結(jié)點到葉子結(jié)點的路。所有關(guān)鍵字查詢的路徑長度相同,導致每一個數(shù)據(jù)的查詢效率相當。


          3、由于B+樹的數(shù)據(jù)都存儲在葉子結(jié)點中,分支結(jié)點均為索引,方便掃庫,只需要掃一遍葉子結(jié)點即可,但是B樹因為其分支結(jié)點同樣存儲著數(shù)據(jù),我們要找到具體的數(shù)據(jù),需要進行一次中序遍歷按序來掃,所以B+樹更加適合在區(qū)間查詢的情況,所以通常B+樹用于數(shù)據(jù)庫索引。


          PS:我在知乎上看到有人是這樣說的,我感覺說的也挺有道理的:


          他們認為數(shù)據(jù)庫索引采用B+樹的主要原因是:B樹在提高了IO性能的同時并沒有解決元素遍歷的我效率低下的問題,正是為了解決這個問題,B+樹應用而生。B+樹只需要去遍歷葉子節(jié)點就可以實現(xiàn)整棵樹的遍歷。而且在數(shù)據(jù)庫中基于范圍的查詢是非常頻繁的,而B樹不支持這樣的操作或者說效率太低。


          B+樹的原理,基本上講完了,限于篇幅,關(guān)于MySQL為啥不用跳表?而Redis鐘情于跳表?咱們下篇再來講述。


          參考文章:

          1、http://blog.csdn.net/whoamiyang/article/details/51926985 
          2、https://www.cnblogs.com/George1994/p/7008732.html 
          3、《MySQL技術(shù)內(nèi)幕 InnoDB存儲引擎 姜承堯 第2版》


          感謝您的閱讀,也歡迎您發(fā)表關(guān)于這篇文章的任何建議,關(guān)注我,技術(shù)不迷茫!小編到你上高速。
              · END ·
          最后,關(guān)注公眾號互聯(lián)網(wǎng)架構(gòu)師,在后臺回復:2T,可以獲取我整理的 Java 系列面試題和答案,非常齊全。


          正文結(jié)束


          推薦閱讀 ↓↓↓

          1.不認命,從10年流水線工人,到谷歌上班的程序媛,一位湖南妹子的勵志故事

          2.如何才能成為優(yōu)秀的架構(gòu)師?

          3.從零開始搭建創(chuàng)業(yè)公司后臺技術(shù)棧

          4.程序員一般可以從什么平臺接私活?

          5.37歲程序員被裁,120天沒找到工作,無奈去小公司,結(jié)果懵了...

          6.IntelliJ IDEA 2019.3 首個最新訪問版本發(fā)布,新特性搶先看

          7.這封“領(lǐng)導痛批95后下屬”的郵件,句句扎心!

          8.15張圖看懂瞎忙和高效的區(qū)別!


          瀏覽 118
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  爱爱视频不卡免费观看 | 色婷婷成人做爰A片免费看网站 | 五月婷婷人妻小说 | 色8视频 色图网址 | x8x8拨牐拨牐精品视频 |