存儲底層數據結構對比 LSM樹由來、設計思想以及應用到HBase的索引

該文章對比了常用的一些存儲底層所使用的數據結構。

1.B+樹

MySQLMongoDB的索引使用的就是B+樹

B+樹在多讀少寫(相對而言)的情境下比較有優勢。

B+樹的主要優點:

  • 1.結構比較扁平,高度低(一般不超過4層),隨機尋道次數少;
  • 2.數據存儲密度大,且都位於葉子節點,查詢穩定,遍歷方便;
  • 3.葉子節點形成有序鏈表,範圍查詢轉化爲順序讀,效率高。相對而言B樹必須通過中序遍歷才能支持範圍查詢。

B+樹的缺點:

  • 1.如果寫入的數據比較離散,那麼尋找寫入位置時,子節點有很大可能性不會在內存中,最終會產生大量的隨機寫,性能下降。
  • 2.如果B+樹已經運行了很長時間,寫入了很多數據,隨着葉子節點分裂,其對應的塊會不再順序存儲,而變得分散。這時執行範圍查詢也會變成隨機讀,效率降低了。

參考:從B+樹到LSM樹,及LSM樹在HBase中的應用

2.LSM樹(Log-structured Merge-Tree/日誌結構的合併樹)

RocksDBHBase,Cassandra底層使用的是LSM樹

LSM樹的優點

  • 1.LSM樹由於數據按順序存儲,因此可以有效地執行區間查詢(從最小值到最大值掃描所有的鍵),並且由於磁盤是順序寫入的(以順序方式寫入緊湊的SSTable文件,而不必重寫樹中的多個頁),所以LSM-Tree可以支持非常高的寫入吞吐量

LSM樹的缺點

  • 1.壓縮過程中有時會干擾正在進行的讀寫操作。即使存儲引擎嘗試增量地執行壓縮,並且不影響併發訪問,但由於磁盤的併發資源有限,所以當磁盤執行昂貴的壓縮操作時,很容易發生讀寫請求等待的情況。而B-tree的響應延遲則更具確定性。

參考:LSM樹由來、設計思想以及應用到HBase的索引 和 數據密集型應用系統設計第3章

3.跳錶

Redis底層使用的是SkipTable

Mysql的索引爲什麼使用B+樹而不使用跳錶?

B+樹是多叉樹結構,每個結點都是一個16k的數據頁,能存放較多索引信息,所以扇出很高。三層左右就可以存儲2kw左右的數據(知道結論就行,想知道原因可以看之前的文章)。也就是說查詢一次數據,如果這些數據頁都在磁盤裏,那麼最多需要查詢三次磁盤IO。

跳錶是鏈表結構,一條數據一個結點,如果最底層要存放2kw數據,且每次查詢都要能達到二分查找的效果,2kw大概在2的24次方左右,所以,跳錶大概高度在24層左右。最壞情況下,這24層數據會分散在不同的數據頁裏,也即是查一次數據會經歷24次磁盤IO。

因此存放同樣量級的數據,B+樹的高度比跳錶的要少,如果放在mysql數據庫上來說,就是磁盤IO次數更少,因此B+樹查詢更快

而針對寫操作,B+樹需要拆分合並索引數據頁,跳錶則獨立插入,並根據隨機函數確定層數,沒有旋轉和維持平衡的開銷,因此跳錶的寫入性能會比B+樹要好

redis爲什麼使用跳錶而不使用B+樹或二叉樹呢?

redis支持多種數據結構,裏面有個有序集合,也叫ZSET。內部實現就是跳錶。那爲什麼要用跳錶而不用B+樹等結構呢?

大家知道,redis 是純純的內存數據庫

進行讀寫數據都是操作內存,跟磁盤沒啥關係,因此也不存在磁盤IO了,所以層高就不再是跳錶的劣勢了。

並且前面也提到B+樹是有一系列合併拆分操作的,換成紅黑樹或者其他AVL樹的話也是各種旋轉,目的也是爲了保持樹的平衡。

而跳錶插入數據時,只需要隨機一下,就知道自己要不要往上加索引,根本不用考慮前後結點的感受,也就少了旋轉平衡的開銷

因此,redis選了跳錶,而不是B+樹。

參考:MySQL的索引爲什麼使用B+樹而不使用跳錶?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章