一、零鋪墊
在介紹b樹之前,先來看另一棵神奇的樹——二叉排序樹(binary sort tree),首先它是一棵樹,「二叉」這個描述已經很明顯了,就是樹上的一根樹枝開兩個叉,於是遞迴下來就是二叉樹了(下圖所示),而這棵樹上的節點是已經排好序的,具體的排序規則如下:
從圖中可以看出,二叉排序樹組織資料時,用於查詢是比較方便的,因為每次經過一次節點時,最多可以減少一半的可能,不過極端情況會出現所有節點都位於同一側,直觀上看就是一條直線,那麼這種查詢的效率就比較低了,因此需要對二叉樹左右子樹的高度進行平衡化處理,於是就有了平衡二叉樹(balenced binary tree)。
所謂「平衡」,說的是這棵樹的各個分支的高度是均勻的,它的左子樹和右子樹的高度之差絕對值小於1,這樣就不會出現一條支路特別長的情況。於是,在這樣的平衡樹中進行查詢時,總共比較節點的次數不超過樹的高度,這就確保了查詢的效率(時間複雜度為o(logn))。
二、b樹的起源
b樹,最早是由德國計算機科學家rudolf bayer等人於2023年在** 《organization and maintenance of large ordered indexes》提出的,不過我去看了看原文,發現作者也沒有解釋為什麼就叫b-trees了,所以把b樹的b,簡單地解釋為balanced或者binary都不是特別嚴謹,也許作者就是取其名字bayer的首字母命名的也說不定啊……
三、b樹長啥樣
還是直接看圖比較清楚,圖中所示,b樹事實上是一種平衡的多叉查詢樹,也就是說最多可以開m個叉(m>=2),我們稱之為m階b樹,為了體現本部落格的良心之處,不同於其他地方都能看到2階b樹,這裡特意畫了一棵5階b樹 。
總的來說,m階b樹滿足以下條件:
b樹的查詢過程和二叉排序樹比較類似,從根節點依次比較每個結點,因為每個節點中的關鍵字和左右子樹都是有序的,所以只要比較節點中的關鍵字,或者沿著指標就能很快地找到指定的關鍵字,如果查詢失敗,則會返回葉子節點,即空指標。
例如查詢圖中字母表中的k
從根節點p開始,k的位置在p之前,進入左側指標
左子樹中,依次比較c、f、j、m,發現k在j和m之間
沿著j和m之間的指標,繼續訪問子樹,並依次進行比較,發現第乙個關鍵字k即為指定查詢的值
四、plus版——b+樹
作為b樹的加強版,b+樹與b樹的差異在於
b+樹的查詢過程,與b樹類似,只不過查詢時,如果在非葉子節點上的關鍵字等於給定值,並不終止,而是繼續沿著指標直到葉子節點位置。因此在b+樹,不管查詢成功與否,每次查詢都是走了一條從根到葉子節點的路徑。
五、mysql是如何使用b樹的
說明:事實上,在mysql資料庫中,諸多儲存引擎使用的是b+樹,即便其名字看上去是btree。
1、innodb的索引機制
先以innodb儲存引擎為例,說明innodb引擎是如何利用b+樹建立索引的。首先建立一張表:zodiac,並插入一些資料
create table `zodiac` (對於innodb來說,只有乙個資料檔案,這個資料檔案本身就是用b+樹形式組織,b+樹每個節點的關鍵字就是表的主鍵,因此innodb的資料檔案本身就是主索引檔案,如下圖所示,主索引中的葉子頁(leaf page)包含了資料記錄,但非葉子節點只包含了主鍵,術語「聚簇」表示資料行和相鄰的鍵值緊湊地儲存在一起,因此這種索引被稱為聚簇索引,或聚集索引。`id` int(11) not null auto_increment,
`name` char(4) not null,
primary key (`id`),
key `index_name` (`name`)
); insert zodiac(id,name) values(1,'鼠');
insert zodiac(id,name) values(2,'牛');
insert zodiac(id,name) values(3,'虎');
insert zodiac(id,name) values(4,'兔');
insert zodiac(id,name) values(5,'龍');
insert zodiac(id,name) values(6,'蛇');
insert zodiac(id,name) values(7,'馬');
insert zodiac(id,name) values(8,'羊');
insert zodiac(id,name) values(9,'猴');
insert zodiac(id,name) values(10,'雞');
insert zodiac(id,name) values(11,'狗');
insert zodiac(id,name) values(12,'豬');
這種索引方式,可以提高資料訪問的速度,因為索引和資料是儲存在同一棵b樹之中,從聚簇索引中獲取資料通常比在非聚簇索引中要來得快。
所以可以說,innodb的資料檔案是依靠主鍵組織起來的,這也就是為什麼innodb引擎下建立的表,必須指定主鍵的原因,如果沒有顯式指定主鍵,innodb引擎仍然會對該表隱式地定義乙個主鍵作為聚簇索引。
同樣innodb的輔助索引,如下圖所示,假設這些字元是按照生肖的順序排列的(其實我也不知道具體怎麼實現,不要在意這些細節,就是舉個例子),其葉子節點中也包含了記錄的主鍵,因此innodb引擎在查詢輔助索引的時候會查詢兩次,首先通過輔助索引得到主鍵值,然後再查詢主索引,略微有點囉嗦。。。
2、myisam的索引機制
myisam引擎同樣也使用b+樹組織索引,如下圖所示,假設我們的資料不是按照之前的順序插入的,而是按照圖中的是順序插入表,可以看到myisam引擎下,b+樹葉子節點中包含的是資料記錄的位址(可以簡單理解為「行號」),而myisam的輔助索引在結構上和主索引沒有本質的區別,同樣其葉子節點也包含了資料記錄的位址,稍微不同的是輔助索引的關鍵字是允許重複。
六、簡單對比
1、innodb輔助索引的葉子節點儲存的不是位址,而是主鍵值,這樣的策略減少了當出現行移動或者資料頁**時輔助索引的維護工作,雖然使用主鍵值當作指標會讓輔助索引占用更多空間,但好處是,innodb在移動行時無需更新輔助索引中的主鍵值,而myisam需要調整其葉子節點中的位址。
2、innodb引擎下,資料記錄是儲存在b+樹的葉子節點(大小相當於磁碟上的頁)上,當插入新的資料時,如果主鍵的值是有序的,它會把每一條記錄都儲存在上一條記錄的後面,但是如果主鍵使用的是無序的數值,例如uuid,這樣在插入資料時innodb無法簡單地把新的資料插入到最後,而是需要為這條資料尋找合適的位置,這就額外增加了工作,這就是innodb引擎寫入效能要略差於myisam的原因之一。
innodb和myisam索引的抽象圖
分類: mysql
mysql中innodb和myisam對比
innodb和myisam是很多人在使用mysql時最常用的兩個表型別,這兩個表型別各有優劣,5.7之後就不一樣了 1 事務和外來鍵 innodb具有事務,支援4個事務隔離級別,回滾,崩潰修復能力和多版本併發的事務安全,包括acid。如果應用中需要執行大量的insert或update操作,則應該使用...
Mysql中,Myisam和Innodb的區別
都說寫部落格就是自我揭醜,但我個人覺得寫這個玩楞就是複習的一種方式,學習怎麼會是自我揭醜呢,我會多少寫多少這樣有毛病麼?當你開啟我這篇部落格的時候,首先恭喜你看到了我人生中第一篇部落格,確實沒啥經驗,也不會寫那麼多吸引眼球的東西,更不是文科出身,不會拽那麼多高大尚的詞彙,碼農出身你懂得 既然是第一篇...
mysql中myisam和 innodb的區別
關於資料庫引擎 innodb 預設使用 myisam 早些年使用的 myisam innodb 事務支援 不支援支援 資料行鎖定 不支援支援 外來鍵約束 不支援支援 全文索引 支援不支援 表空間的大小 較小較大 大約為mysiam的2倍 常規使用操作 在物理空間存在的位置 所有的資料檔案都存在dat...