B樹指的是一類樹,包括B-樹,B+樹,B*樹等,是一種自平衡的搜索樹,它相似普通的平衡二叉樹,不一樣的一點是B樹容許每一個節點有更多的子節點。B樹是專門爲外部存儲器設計的,如磁盤,它對於讀取和寫入大塊數據有良好的性能,因此通常用在文件系統及數據庫中。
傳統用來搜索的平衡二叉樹有不少,AVL樹,紅黑樹等。這些樹在通常狀況下的查詢性能很是好,但當數據量很是大的時候就無能爲力了。數據量很是大時,內存不夠用,大部分數據只能存放在磁盤上,只有須要的數據才加載到內存。通常而言內存的訪問時間爲50ns,而磁盤在10ms左右。速度相差了近5個數量級,程序大部分的時間阻塞在磁盤IO上。因此核心就是要減小磁盤IO次數。而像AVL樹,紅黑樹這類平衡二叉樹從設計上沒法"迎合"磁盤。mysql
上圖是一顆簡單的平衡二叉樹,咱們來看下爲何數據庫和文件系統用b樹而不用平衡二叉樹:redis
(1) 它的平衡是經過旋轉來實現的,而旋轉是對整個樹的操做,若部分加載到內存中則沒法完成旋轉操做。sql
(2) 平衡二叉樹的高度比較大(log n), 這樣邏輯上很近的節點實際可能很是遠,沒法很好地利用磁盤預讀(空間的局部性原理)數據庫
索引的效率實際上依賴於磁盤IO的次數,加快索引的辦法就是有效地減小磁盤IO次數。相比於平衡二叉樹每次將範圍分割爲兩個區間,B樹每次將範圍分割成多個區間,區間越多,定位數據越快越精確。多叉下降了B樹的高度(底數很大的log n,二叉是底數爲2). 那麼節點爲區間範圍,每一個節點就比較大了。所以新建節點時,直接申請頁大小的空間(磁盤時按照block分的,通常爲512 byte。磁盤IO一次讀取若干個block,咱們稱爲一頁,具體大小和操做系統有關,通常爲4k,8k或16k),計算機內存分配是按頁對齊的,這樣一個節點只須要一次IO。那麼多叉樹的總IO次數也就縮減爲log n次。json
上面是一顆B-樹,B-樹的插入和刪除就不具體介紹了,不少資料都描述了這一過程。在普通平衡二叉樹中,插入刪除後若不知足平衡條件則進行 旋轉 操做,而在B-樹中,插入刪除後不知足條件則進行分裂及合併操做。nosql
咱們來看看B-樹的查找,假設每一個節點有 n 個 key值,被分割爲 n+1 個區間,注意,每一個 key 值緊跟着 data 域,這說明B-樹的 key 和 data 是聚合在一塊兒的。通常而言,根節點都在內存中,B-樹以每一個節點爲一次磁盤 IO,好比上圖中,若搜索 key 爲 25 節點的 data,首先在根節點進行二分查找(由於 keys 有序,二分最快),判斷 key 25 小於 key 50,因此定位到最左側的節點,此時進行一次磁盤 IO,將該節點從磁盤讀入內存,接着繼續進行上述過程,直到找到該 key 爲止。性能
B+樹是B-樹的變種,它與B-樹的不一樣之處在於:mysql索引
由於內節點並不存儲 data,因此通常B+樹的葉節點和內節點大小不一樣,而B-樹的每一個節點大小通常是相同的,爲一頁。優化
爲了增長 區間訪問性,通常會對B+樹作一些優化。
以下圖帶順序訪問的B+樹。網站
B+樹節點不存儲數據,全部data存儲在葉節點致使查詢時間負責度固定爲log n。而B-樹查詢時間複雜度不固定,與key在樹中的位置有關,最好爲O(1)
下面爲圖示:
B-樹
從上圖能夠看出,key 爲 50 的節點就在第一層,B-樹只須要一次磁盤 IO 便可完成查找。因此說B-樹的查詢最好時間複雜度是 O(1)。
B+樹
因爲B+樹全部的 data 域都在根節點,因此查詢 key 爲 50的節點必須從根節點索引到葉節點,時間複雜度固定爲 O(log n)。
B+樹葉節點兩兩相連可大大增長區間訪問性,可以使用在範圍查詢等,而B-樹每一個節點key 和data在一塊兒,則沒法區間查找
B+樹能夠很好的利用局部性原理,若咱們訪問節點 key爲 50,則 key 爲 5五、60、62 的節點未來也可能被訪問,咱們能夠利用磁盤預讀原理提早將這些數據讀入內存,減小了磁盤 IO 的次數。
固然B+樹也可以很好的完成範圍查詢。好比查詢 key 值在 50-70 之間的節點。
這個很好理解,因爲B-樹節點內部每一個 key 都帶着 data 域,而B+樹節點只存儲 key 的副本,真實的 key 和 data 域都在葉子節點存儲。前面說過磁盤是分 block 的,一次磁盤 IO 會讀取若干個 block,具體和操做系統有關,那麼因爲磁盤 IO 數據大小是固定的,在一次 IO 中,單個元素越小,量就越大。這就意味着B+樹單次磁盤 IO 的信息量大於B-樹,從這點來看B+樹相對B-樹磁盤 IO 次數少。
從上圖能夠看出相同大小的區域,B-樹僅有 2 個 key,而B+樹有 3 個 key。
mysql是傳統的關係型數據庫,而MongoDB是文檔形的數據庫,是一種nosql,它使用xml或json格式來保存數據,歸屬於聚合型數據庫。(鍵值數據庫也屬於聚合型數據庫,好比redis)
咱們要創建一個電子商務網站,相似淘寶這種將商品銷售給用戶,那麼必須存儲用戶信息、商品目錄、訂單、收貨地址、帳單地址、付款方式等。
(1)傳統的關係型數據庫模型
(2)聚合型數據庫存儲模型
用相似json的格式表示以下:
//Customer { "id":1, "name":Tom, "billingAddress":[{"city":"China"}] } //Orders { "id":99, "orderItem":[ "productId"27, "price":100, "productName":book ], "shippingAddress":[{"city":"china"}], "orderPayment":[ ... ] }
相對於 Mysql 關係型數據庫,MongoDB 這類 nosql 適用於數據模型簡單,性能要求高的場合
MongoDB 是一種 nosql,也存儲在磁盤上,被設計用在 數據模型簡單,性能要求高的場合。上面說過,儘可能減小磁盤IO是提升性能的有效手段,而B-樹剛好key和data域聚合在一塊兒,複雜度最好爲O(1)。
(1) Mysql 是一種關係型數據庫,區間訪問是常見的一種狀況,而 B-樹並不支持區間訪問,而B+樹因爲數據所有存儲在葉子節點,而且經過指針串在一塊兒,這樣就很容易的進行區間遍歷甚至所有遍歷
(2) 其次B+樹的查詢效率更加穩定,數據所有存儲在葉子階段,查詢時間複雜度固定爲O(log n)。
(3) B+樹更適合外部存儲,因爲內節點無data域,每一個節點能索引的範圍更大更精確
摘自: http://blog.csdn.net/wwh578867817/article/details/50493940