關(guān)于二叉查找查找樹殖蚕、平衡二叉樹轿衔、平衡多路查找樹(B-Tree)以及B+Tree

B+樹是在數(shù)據(jù)庫中的一種實現(xiàn),是數(shù)據(jù)庫中使用最頻繁的一種索引睦疫。B+樹中的B是balance的縮寫代表平衡害驹,,而不是二叉樹(binary)蛤育,但是B+樹確實是從最早的平衡二叉樹演變而來的宛官,因此本文在講B+Tree之前,還是會大致梳理一遍二叉查找樹瓦糕、平衡二叉樹和平衡多路查找樹的知識底洗。

二叉查找樹

二叉樹查找樹具有以下特點:
左子樹的鍵值小于根的鍵值,右子樹的鍵值大于根的鍵值

如圖

對二叉樹節(jié)點進行查找時深度為1查找次數(shù)為1咕娄,深度為n節(jié)點的查找次數(shù)為n
但是如果一顆二叉查找樹兩側(cè)深度差距過大亥揖,就會使效率大打折扣,于是出現(xiàn)了二叉平衡樹

平衡二叉樹(AVL Tree)

二叉平衡樹(AL Tree)是在符合二叉查找樹的條件下圣勒,還需要滿足以下條件:任何節(jié)點的兩個字?jǐn)?shù)的高度差最大為1

image.png

如果在AVL樹中進行插入或刪除節(jié)點费变,可能導(dǎo)致AVL樹失去平衡,這種失去平衡的二叉樹可以概括為四種姿態(tài):LL(左左)灾而、RR(右右)胡控、LR(左右)、RL(右左)旁趟。


分別為LL昼激、LR庇绽、RL、RR

要想將失去平衡的樹恢復(fù)平衡大致方法可以概括為:將高度較高的一端的節(jié)點作為根節(jié)點橙困,調(diào)整原根節(jié)點和子節(jié)點位置即可

平衡多路查找樹(B-Tree)

B-Tree是為磁盤等外存儲設(shè)備設(shè)計的一種平衡查找樹瞧掺。因此在講B-Tree之前先了解下磁盤的相關(guān)知識。

系統(tǒng)從磁盤讀取數(shù)據(jù)到內(nèi)存時是以磁盤塊(block)為基本單位的凡傅,位于同一個磁盤塊中的數(shù)據(jù)會被一次性讀取出來辟狈,而不是需要什么取什么。

InnoDB存儲引擎中有頁(Page)的概念夏跷,頁是其磁盤管理的最小單位哼转。InnoDB存儲引擎中默認(rèn)每個頁的大小為16KB,可通過參數(shù)innodb_page_size將頁的大小設(shè)置為4K槽华、8K壹蔓、16K

而系統(tǒng)一個磁盤塊的存儲空間往往沒有這么大,因此InnoDB每次申請磁盤空間時都會是若干地址連續(xù)磁盤塊來達到頁的大小16KB猫态。InnoDB在把磁盤數(shù)據(jù)讀入到磁盤時會以頁為基本單位佣蓉,在查詢數(shù)據(jù)時如果一個頁中的每條數(shù)據(jù)都能有助于定位數(shù)據(jù)記錄的位置,這將會減少磁盤I/O次數(shù)亲雪,提高查詢效率勇凭。

B-Tree結(jié)構(gòu)的數(shù)據(jù)可以讓系統(tǒng)高效的找到數(shù)據(jù)所在的磁盤塊。為了描述B-Tree义辕,首先定義一條記錄為一個二元組[key, data] 虾标,key為記錄的鍵值,對應(yīng)表中的主鍵值终息,data為一行記錄中除主鍵外的數(shù)據(jù)夺巩。對于不同的記錄贞让,key值互不相同周崭。

一棵m階的B-Tree有如下特性:

  1. 每個節(jié)點最多有m個孩子。
  2. 除了根節(jié)點和葉子節(jié)點外喳张,其它每個節(jié)點至少有Ceil(m/2)個孩子续镇。
  3. 若根節(jié)點不是葉子節(jié)點,則至少有2個孩子
  4. 所有葉子節(jié)點都在同一層销部,且不包含其它關(guān)鍵字信息
  5. 每個非終端節(jié)點包含n個關(guān)鍵字信息(P0,P1,…Pn, k1,…kn)
  6. 關(guān)鍵字的個數(shù)n滿足:ceil(m/2)-1 <= n <= m-1
  7. ki(i=1,…n)為關(guān)鍵字摸航,且關(guān)鍵字升序排序。
  8. Pi(i=1,…n)為指向子樹根節(jié)點的指針舅桩。P(i-1)指向的子樹的所有節(jié)點關(guān)鍵字均小于ki酱虎,但都大于k(i-1)

B-Tree中的每個節(jié)點根據(jù)實際情況可以包含大量的關(guān)鍵字信息和分支,如下圖所示為一個3階的B-Tree:

B-Tree

每個節(jié)點占用一個盤塊的磁盤空間擂涛,一個節(jié)點上有兩個升序排序的關(guān)鍵字和三個指向子樹根節(jié)點的指針读串,指針存儲的是子節(jié)點所在磁盤塊的地址。兩個關(guān)鍵詞劃分成的三個范圍域?qū)?yīng)三個指針指向的子樹的數(shù)據(jù)的范圍域。以根節(jié)點為例恢暖,關(guān)鍵字為17和35排监,P1指針指向的子樹的數(shù)據(jù)范圍為小于17,P2指針指向的子樹的數(shù)據(jù)范圍為17~35杰捂,P3指針指向的子樹的數(shù)據(jù)范圍為大于35舆床。

模擬查找關(guān)鍵字29的過程:

1.根據(jù)根節(jié)點找到磁盤塊1,讀入內(nèi)存嫁佳“ざ樱【磁盤I/O操作第1次】
2.比較關(guān)鍵字29在區(qū)間(17,35),找到磁盤塊1的指針P2蒿往。
3.根據(jù)P2指針找到磁盤塊3瞒瘸,讀入內(nèi)存∠ㄅǎ【磁盤I/O操作第2次】
4.比較關(guān)鍵字29在區(qū)間(26,30)情臭,找到磁盤塊3的指針P2。
5.根據(jù)P2指針找到磁盤塊8赌蔑,讀入內(nèi)存俯在。【磁盤I/O操作第3次】
6.在磁盤塊8中的關(guān)鍵字列表中找到關(guān)鍵字29娃惯。

分析上面過程跷乐,發(fā)現(xiàn)需要3次磁盤I/O操作,和3次內(nèi)存查找操作趾浅。由于內(nèi)存中的關(guān)鍵字是一個有序表結(jié)構(gòu)愕提,可以利用二分法查找提高效率。而3次磁盤I/O操作是影響整個B-Tree查找效率的決定因素皿哨。B-Tree相對于AVLTree縮減了節(jié)點個數(shù)浅侨,使每次磁盤I/O取到內(nèi)存的數(shù)據(jù)都發(fā)揮了作用,從而提高了查詢效率证膨。

B+Tree

B+Tree是在B-Tree基礎(chǔ)上的一種優(yōu)化如输,使其更適合實現(xiàn)外存儲索引結(jié)構(gòu),InnoDB存儲引擎就是用B+Tree實現(xiàn)其索引結(jié)構(gòu)央勒。

從上一節(jié)中的B-Tree結(jié)構(gòu)圖中可以看到每個節(jié)點中不僅包含數(shù)據(jù)的key值不见,還有data值。而每一個頁的存儲空間是有限的崔步,如果data數(shù)據(jù)較大時將會導(dǎo)致每個節(jié)點(即一個頁)能存儲的key的數(shù)量很小稳吮,當(dāng)存儲的數(shù)據(jù)量很大時同樣會導(dǎo)致B-Tree的深度較大,增大查詢時的磁盤I/O次數(shù)井濒,進而影響查詢效率灶似。在B+Tree中慎陵,所有數(shù)據(jù)記錄節(jié)點都是按照鍵值大小順序存放在同一層的葉子節(jié)點上,而非葉子節(jié)點上只存儲key值信息喻奥,這樣可以大大加大每個節(jié)點存儲的key值數(shù)量席纽,降低B+Tree的高度。

B+Tree相對于B-Tree有幾點不同:

1.非葉子節(jié)點只存儲鍵值信息撞蚕。
2.所有葉子節(jié)點之間都有一個鏈指針润梯。
3.數(shù)據(jù)記錄都存放在葉子節(jié)點中。

將上一節(jié)中的B-Tree優(yōu)化甥厦,由于B+Tree的非葉子節(jié)點只存儲鍵值信息纺铭,假設(shè)每個磁盤塊能存儲4個鍵值及指針信息,則變成B+Tree后其結(jié)構(gòu)如下圖所示:


B+Tree

通常在B+Tree上有兩個頭指針刀疙,一個指向根節(jié)點舶赔,另一個指向關(guān)鍵字最小的葉子節(jié)點,而且所有葉子節(jié)點(即數(shù)據(jù)節(jié)點)之間是一種鏈?zhǔn)江h(huán)結(jié)構(gòu)谦秧。因此可以對B+Tree進行兩種查找運算:一種是對于主鍵的范圍查找和分頁查找竟纳,另一種是從根節(jié)點開始,進行隨機查找疚鲤。

可能上面例子中只有22條數(shù)據(jù)記錄锥累,看不出B+Tree的優(yōu)點,下面做一個推算:

InnoDB存儲引擎中頁的大小為16KB集歇,一般表的主鍵類型為INT(占用4個字節(jié))或BIGINT(占用8個字節(jié))桶略,指針類型也一般為4或8個字節(jié),也就是說一個頁(B+Tree中的一個節(jié)點)中大概存儲16KB/(8B+8B)=1K個鍵值(因為是估值诲宇,為方便計算际歼,這里的K取值為[10]^3)。
也就是說一個深度為3的B+Tree索引可以維護10 ^ 3 * 10^3 * 10^3 = 10億 條記錄姑蓝。
實際情況中每個節(jié)點可能不能填充滿鹅心,因此在數(shù)據(jù)庫中,B+Tree的高度一般都在2~4層它掂。mysql的InnoDB存儲引擎在設(shè)計時是將根節(jié)點常駐內(nèi)存的巴帮,也就是說查找某一鍵值的行記錄時最多只需要1~3次磁盤I/O操作溯泣。

數(shù)據(jù)庫中的B+Tree索引可以分為聚集索引(clustered index)和輔助索引(secondary index)虐秋。上面的B+Tree示例圖在數(shù)據(jù)庫中的實現(xiàn)即為聚集索引,聚集索引的B+Tree中的葉子節(jié)點存放的是整張表的行記錄數(shù)據(jù)垃沦。輔助索引與聚集索引的區(qū)別在于輔助索引的葉子節(jié)點并不包含行記錄的全部數(shù)據(jù)客给,而是存儲相應(yīng)行數(shù)據(jù)的聚集索引鍵,即主鍵肢簿。當(dāng)通過輔助索引來查詢數(shù)據(jù)時靶剑,InnoDB存儲引擎會遍歷輔助索引找到主鍵蜻拨,然后再通過主鍵在聚集索引中找到完整的行記錄數(shù)據(jù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末桩引,一起剝皮案震驚了整個濱河市缎讼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坑匠,老刑警劉巖血崭,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異厘灼,居然都是意外死亡夹纫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門设凹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舰讹,“玉大人,你說我怎么就攤上這事闪朱≡孪唬” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵奋姿,是天一觀的道長桶错。 經(jīng)常有香客問我,道長胀蛮,這世上最難降的妖魔是什么院刁? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮粪狼,結(jié)果婚禮上退腥,老公的妹妹穿的比我還像新娘。我一直安慰自己再榄,他們只是感情好狡刘,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著困鸥,像睡著了一般嗅蔬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上疾就,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天澜术,我揣著相機與錄音,去河邊找鬼猬腰。 笑死鸟废,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的姑荷。 我是一名探鬼主播盒延,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缩擂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了添寺?” 一聲冷哼從身側(cè)響起胯盯,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎计露,沒想到半個月后陨闹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡薄坏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年趋厉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胶坠。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡君账,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沈善,到底是詐尸還是另有隱情乡数,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布闻牡,位于F島的核電站净赴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏罩润。R本人自食惡果不足惜玖翅,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望割以。 院中可真熱鬧金度,春花似錦、人聲如沸严沥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽消玄。三九已至跟伏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翩瓜,已是汗流浹背受扳。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奥溺,地道東北人辞色。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像浮定,于是被迫代替她去往敵國和親相满。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355