做爲一名應用系統開發人員,爲何要關注數據內部的存儲和檢索呢?首先,你不太可能從頭開始實現一套本身的存儲引擎,每每須要從衆多現有的存儲引擎中選擇一個適合本身應用的存儲引擎。所以,爲了針對你特定的工做負載而對數據庫調優時,最好對存儲引擎的底層機制有一個大概的瞭解。算法
今天咱們就先來了解下關係型數據庫MySQL和NoSQL存儲引擎HBase的底層存儲機制。對於一個數據庫的性能來講,其數據的組織方式相當重要。衆所周知,數據庫的數據大多存儲在磁盤上,而磁盤的訪問相對內存的訪問來講是一項很耗時的操做,對好比下。所以,提升數據庫數據的查找速度的關鍵點之一即是儘可能減小磁盤的訪問次數。數據庫
磁盤與內存的訪問速度對比爲了加速數據庫數據的訪問,大多傳統的關係型數據庫都會使用特殊的數據結構來幫助查找數據,這種數據結構叫做索引( Index)。對於傳統的關係型數據庫,考慮到常常須要範圍查找某一批數據,所以其索引通常不使用 Hash算法,而使用樹( Tree)結構。然而,樹結構的種類不少,卻不必定都適合用於作數據庫索引。緩存
二叉查找樹與平衡二叉樹微信
最多見的樹結構是二叉查找樹( Binary Search Tree),它就是一棵二叉有序樹:保證左子樹上全部節點的值都小於根節點的值,而右子樹上全部節點的值都大於根節點的值。其優勢在於實現簡單,而且樹在平衡的狀態下查找效率能達到 O(log n);缺點是在極端非平衡狀況下查找效率會退化到 O(n),所以很難保證索引的效率。數據結構
二叉查找樹的查找效率針對上述二叉查找樹的缺點,人們很天然就想到是否能用平衡二叉樹( Balanced Binary Tree)來解決這個問題。可是平衡二叉樹依然有個比較大的問題:它的樹高爲 log n——對於索引樹來講,樹的高度越高,意味着查找所要花費的訪問次數越多,查詢效率越低。架構
何況,主存從磁盤讀數據通常以頁爲單位,所以每次訪問磁盤都會讀取多個扇區的數據(好比 4KB大小的數據),遠大於單個二叉樹節點的值(字節級別),這也是形成二叉樹相對索引樹效率低下的緣由。正因如此,人們就想到了經過增長每一個樹節點的度來提升訪問效率,而 B+樹(B+-tree)便受到了更多的關注。分佈式
B+樹性能
在傳統的關係型數據庫裏, B+樹( B+-tree)及其衍生樹是被用得比較多的索引樹。大數據
B+樹B+樹的主要特色以下。 每一個樹節點只存放鍵值,不存放數值,而由葉子節點存放數值。這樣會使樹節點的度比較大,而樹的高度就比較低,從而有利於提升查詢效率。 葉子節點存放數值,並按照值大小順序排序,且帶指向相鄰節點的指針,以便高效地進行區間數據查詢;而且全部葉子節點與根節點的距離相同,所以任何查詢的效率都很類似。 與二叉樹不一樣, B+樹的數據更新操做不從根節點開始,而從葉子節點開始,而且在更新過程當中樹能以比較小的代價實現自平衡。指針
正是因爲 B+樹的上述優勢,它成了傳統關係型數據庫的寵兒。固然,它也並不是無懈可擊,它的主要缺點在於隨着數據插入的不斷髮生,葉子節點會慢慢分裂——這可能會致使邏輯上本來連續的數據實際上存放在不一樣的物理磁盤塊位置上,在作範圍查詢的時候會致使較高的磁盤 IO,以至嚴重影響到性能。
日誌結構合併樹
衆所周知,數據庫的數據大多存儲在磁盤上,而不管是傳統的機械硬盤( HardDiskDrive, HDD)仍是固態硬盤( Solid State Drive, SSD),對磁盤數據的順序讀寫速度都遠高於隨機讀寫。
磁盤順序與隨機訪問吞吐對比然而,基於 B+樹的索引結構是違背上述磁盤基本特色的——它會須要較多的磁盤隨機讀寫,因而, 1992年,名爲日誌結構( Log-Structured)的新型索引結構方法便應運而生。日誌結構方法的主要思想是將磁盤看做一個大的日誌,每次都將新的數據及其索引結構添加到日誌的最末端,以實現對磁盤的順序操做,從而提升索引性能。不過,日誌結構方法也有明顯的缺點,隨機讀取數據時效率很低。
1996年,一篇名爲 Thelog-structured merge-tree(LSM-tree)的論文創造性地提出了日誌結構合併樹( Log-Structured Merge-Tree)的概念,該方法既吸取了日誌結構方法的優勢,又經過將數據文件預排序克服了日誌結構方法隨機讀性能較差的問題。儘管當時 LSM-tree新穎且優點鮮明,但它真正聲名鵲起倒是在 10年以後的 2006年,那年穀歌的一篇使用了 LSM-tree技術的論文 Bigtable: A Distributed Storage System for Structured Data橫空出世,在分佈式數據處理領域掀起了一陣旋風,隨後兩個聲名赫赫的大數據開源組件( 2007年的 HBase與 2008年的 Cassandra,目前二者同爲 Apache頂級項目)直接在其思想基礎上破繭而出,完全改變了大數據基礎組件的格局,同時也極大地推廣了 LSM-tree技術。
LSM-tree最大的特色是同時使用了兩部分類樹的數據結構來存儲數據,並同時提供查詢。其中一部分數據結構( C0樹)存在於內存緩存(一般叫做 memtable)中,負責接受新的數據插入更新以及讀請求,並直接在內存中對數據進行排序;另外一部分數據結構( C1樹)存在於硬盤上 (這部分一般叫做 sstable),它們是由存在於內存緩存中的 C0樹衝寫到磁盤而成的,主要負責提供讀操做,特色是有序且不可被更改。
LSM-tree的 C0與 C1部分LSM-tree的另外一大特色是除了使用兩部分類樹的數據結構外,還會使用日誌文件(一般叫做 commit log)來爲數據恢復作保障。這三類數據結構的協做順序通常是:全部的新插入與更新操做都首先被記錄到 commit log中——該操做叫做 WAL(Write Ahead Log),而後再寫到 memtable,最後當達到必定條件時數據會從 memtable衝寫到 sstable,並拋棄相關的 log數據; memtable與 sstable可同時供查詢;當 memtable出問題時,可從 commit log與 sstable中將 memtable的數據恢復。
咱們能夠參考 HBase的架構來體會其架構中基於 LSM-tree的部分特色。按照 WAL的原則,數據首先會寫到 HBase的 HLog(至關於 commit log)裏,而後再寫到 MemStore(至關於 memtable)裏,最後會衝寫到磁盤 StoreFile(至關於 sstable)中。這樣 HBase的 HRegionServer就經過 LSM-tree實現了數據文件的生成。HBase LSM-tree架構示意圖以下圖。
HBase LSM-tree架構示意圖LSM-tree的這種結構很是有利於數據的快速寫入(理論上能夠接近磁盤順序寫速度),可是不利於讀——由於理論上讀的時候可能須要同時從 memtable和全部硬盤上的 sstable中查詢數據,這樣顯然會對性能形成較大的影響。爲了解決這個問題, LSM-tree採起了如下主要的相關措施。
總結
LSM樹和B+樹的差別主要在於讀性能和寫性能進行權衡,在犧牲的同時尋找其他補救方案。
B+樹存儲引擎,不只支持單條記錄的增、刪、讀、改操做,還支持順序掃描(B+樹的葉子節點之間的指針),對應的存儲系統就是關係數據庫。但隨着寫入操做增多,爲了維護B+樹結構,節點分裂,讀磁盤的隨機讀寫機率會變大,性能會逐漸減弱。LSM樹(Log-Structured MergeTree)存儲引擎和B+樹存儲引擎同樣,一樣支持增、刪、讀、改、順序掃描操做。並且經過批量存儲技術規避磁盤隨機寫入問題。固然凡事有利有弊,LSM樹和B+樹相比,LSM樹犧牲了部分讀性能,用來大幅提升寫性能。 訂閱關注微信公衆號《大數據技術進階》,及時獲取更多大數據架構和應用相關技術文章!