數據結構--樹形結構

  • 平衡二叉樹

    這裏寫圖片描述

這是個平衡樹,一個節點下只有小於兩個子葉節點。

該樹想要達成有效查找,勢必需要維持如下一種結構:
    樹的子葉節點中,左子樹一定小於等於當前節點,而當前節點的右子樹則一定大於當前節點。只有這樣,才能夠維持全局有序,才能夠進行查詢。
    這也就決定了只有取得某一個子葉節點後,才能夠根據這個節點知道他的子樹的具體的值情況。這點非常之重要,因爲二叉平衡樹,只有兩個子葉節點,所以如果想找到某個數據,他必須重複更多次“拿到一個節點的兩個子節點,判斷大小,再從其中一個子節點取出他的兩個子節點,判斷大小。”這一過程。
    這個過程重複的次數,就是**樹的高度**。那麼既然每個子樹只有兩個節點,那麼N個數據的樹的高度也就很容易可以算出了。

樹的存儲結構:
    順序存儲結構:類似數組形式(查詢快,插入慢)
    鏈式存儲結構:類似鏈表形式(查詢的時候需要大量的尋道時間)

優點:
    沒有空間浪費,不會存在空餘的空間,而且查詢速度比較快。

缺點:
    需要取出多個節點,且無法預測下一個節點的位置。這種取出的操作,在內存內進行的時候,速度很快,但如果到磁盤,那麼就意味着大量隨機尋道。基本磁盤就被查死了。
  • b樹
b樹:平衡二叉樹+順序存儲結構
    b樹,因爲其構建過程中引入了有序數組,從而有效的降低了樹的高度,一次取出一個連續的數組,這個操作在磁盤上比取出與數組相同數量的離散數據,要便宜的多。因此磁盤上基本都是b樹結構。

缺點:
    與二叉樹相比,他會耗費更多的空間。在最惡劣的情況下,要有幾乎是元數據兩倍的格子才能裝得下整個數據集(當樹的所有節點都進行了分裂後)。

b樹插入:

這裏寫圖片描述

B樹在插入的時候,如果是最後一個node,那麼速度非常快,因爲是順序寫。

b樹更新:

這裏寫圖片描述
但如果有更新插入刪除等綜合寫入,最後因爲需要循環利用磁盤塊,所以會出現較多的隨機io.大量時間消耗在磁盤尋道時間上。

運行時間很長的b樹:

這裏寫圖片描述

如果是一個運行時間很長的b樹,那麼幾乎所有的請求,都是隨機io。因爲磁盤塊本身已經不再連續,很難保證可以順序讀取。

如何能夠解決這個問題呢?

1: 放棄部分讀性能,使用更加面向順序寫的樹的結構來提升寫性能:
(1),COLA(Cache-Oblivious Look ahead Array)(代表應用自然是tokuDB)。
(2),LSM tree(Log-structured merge Tree)或SSTABLE(代表的數據集是cassandra,hbase,bdb java editon,levelDB etc.)
2:使用ssd,讓尋道成爲往事。

  • B+樹
B+樹:平衡二叉樹+鏈式存儲結構
    b+樹在查詢過程中應該是不會慢的,但如果數據插入比較無序的時候,比如先插入5 然後10000然後3然後800 這樣跨度很大的數據的時候,就需要先“找到這個數據應該被插入的位置”,然後插入數據。這個查找到位置的過程,如果非常離散,那麼就意味着每次查找的時候,他的子節點都不在內存中,這時候就必須使用磁盤尋道時間查找。更新基本與插入是相同的。
    目前關係型數據庫大部分採用該存儲結構。
  • LSM樹
理解:在內存進行寫操作(插入、修改、刪除),達到一定閥值之後,持久化到磁盤。
    數據首先會插入內存中的樹。當內存樹的數據量超過設定閾值後,會進行合併操作。合併操作會從左至右便利內存中樹的子節點 與 磁盤中樹的子節點並進行合併,會用最新更新的數據覆蓋舊的數據(或者記錄爲不同版本)。當被合併合併數據量達到磁盤的存儲頁大小時。會將合併後的數據(有序的)持久化到磁盤,同時更新父節點對子節點的指針。(類似於定時對磁盤中的數據排序)
    讀數據:從磁盤中把父節點的數據拿出來,在內存中緩存。
    寫數據:如果內存中有該節點的數據,則進行直接進行操作。如果不存在則進行讀數據。達到一定閥值後持久化到磁盤上。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章