在目前的Mysql數據庫中,使用最廣泛的是innodb存儲引擎。innodb確實是個很不錯的存儲引擎,就連高性能Mysql里都說了,如果不是有什么很特別的要求,innodb就是最好的選擇。當然,這偏文章講的是TokuDB,不是innodb,相比innodb,TokuDB有着自己的特點。
轉自:http://www.kryptosx.info/archives/931.html
BTree和Fractal tree的比較:
目前無論是SQL Server,還是MySQL的innodb,都是用的B+Tree(SQL Server用的是標准的B-Tree)的索引結構。從理論上來說,這個結構在查詢過程中應該是不會慢的,此類基於比較的數據結構查詢復平均雜度都是logn。B類樹就是對於這個進行了優化,讓它更適應磁盤,降低樹的深度。
隨機IO幾乎是令所有DBA談虎色變的一個問題,當數據量小的時候,所有數據都能到內存中那就沒有這個問題(其實這個時候也就沒有必要用B-Tree的這種塊結構了),但是一旦數據量大於內存的話這個問題就出現了。其實從本質來說,k-v存儲要解決的問題就是這么一個:盡可能快得寫入,以及盡可能快的讀取。
這也是設計數據結構時考慮最多的問題,在分析解決方法之前,我們討論幾個極端。走一個極端的話,如果我每次寫數據都順序寫,那么對Insert來說的話是最快的,但是每次Query就需要Scan一遍整個表。那么如果我想獲取最佳的讀性能,那么方法就是像B-Tree那樣全部排個序唄。但是因為B-Tree有那樣的隨機IO,這樣我們有沒有辦法得到順序寫的寫性能,
所以,TokuDB中使用了一個稱之為Fractal tree(分形樹)的索引結構來解決隨機IO的問題。它主要是能讓隨機IO變成順序IO。
Structure | Inserts | Point Queries | Range Queries |
B-Tree | Horrible | Good | Good (young) |
Append | Wonderful | Horrible | Horrible |
Fractal Tree | Good | Good | Good |
Fractal tree(分形樹)簡介
我們假設有這樣一種集合的結構,相鄰行空間加倍。每一行要么全滿要么全空,全滿行的數據都是排好序的。
數據插入:
以上圖的數據存儲狀態為例,如果再寫一個值的時候,會寫在第一行,比如寫了3,這個時候第一行是空的,所以就放到第一行。
再寫一個值11的時候,因為第一行已經寫滿了,所以將3取出來,和11做排序,嘗試寫第二行。
又因為第二行也滿了,所以將第二行的5和10也取出,對3,11,5,10進行排序。寫入第三行。
最后的結果:
總體來看:
可以看出,這個數據結構能保證數據塊都是滿的。如果前面都滿了,就會一層層合並下去,直到找到可以寫入的塊。
沒明白的:
插入復雜度為O(log(N)/B),B是一個塊存儲的數據行數,N是數據量。但是我只想到O(N/B)的復雜度。據說是進行了優化得到的,不過沒看懂。
提一下:BTree的復雜度為O(log(N)/log(B)),這是樹的深度。B其實就是樹的度,樹的度越大,深度越低,成對數關系。
總結下Fractal Tree結構特點
- 由多個有序的數組構成,大小呈指數級增長
- 數組要么全空,要么全滿
- 數據插入到最小的數組,如果空間不夠就將數據進行Merge
查詢性能:
如果不進行優化,查詢性能並不好。我們需要掃描每一層,最壞情況下IO次數達 log2N。
為了提高查找的性能,TokuDB在每個數據上加了一個forwardpointer,指向下一行中第一個比它大的數據的位置(這個叫做Fractional Cascading)。平均地看,上一級的每個數都把下一級搜索范圍限制到了常數個,所以磁盤IO的次數最差應該為O(logN)。
看到的另一種優化辦法:
總結:
TokuDB主要的優點在於把隨機的IO轉換成順序的IO寫入。因此獲得很好的寫入速度,也因為這個,有很好的數據壓縮效果。但如果是順序寫入,性能不如BTree。
因此,它適用於存檔,大量隨機插入的場景。