目錄
RocksDB Compaction 成本分析(逐層緩存,Batch合併):
Append寫入收益:
- SSD友好:追加寫vs隨機寫
- CPU緩存友好:減少鏈表的訪問方式
- CPU多核友好:
- LockFree,無Page鎖,可以做到行級鎖或者行級無鎖。提升多核場景下CPU緩存命中。
- 追加寫,不原地修改數據,提升多核CPU 緩存命中率。
Append成本分析:
首先分析Append方式對數據訪問的影響:
在常見的數據庫系統中,對數據的訪問通常分爲兩大部分:確認在哪個Page,然後在Page內進行快速查找(比如N分查找)。
Append更新方式都是在page這個級別進行的,比如:
- BwTree是在物理Page上進行Append。
- RocksDB是在邏輯Page(某個範圍的Row組成的邏輯Page)上進行Append。
其原因是於Row的粒度過於細,訪問成本過高。具體分析是:由於Append更新,導致Page的物理位置常規性發生變化。這裏可以採用Page層面甚至是SSt層面的路由進行進行管理。如果是在Row粒度上,要採用Row級別粒度的路由信息。路由信息大概在50倍的膨脹,路由信息難於管理,並且在Compaction過程中(後面會提到)開銷也很高(因爲移動數據的時候要改Row的路由信息)
由上述更新方式,導致Page的版本鏈較長。較長的版本鏈會導致CPU訪問性能下降、IO次數變多。
Compaction的目標:
有上述分析可以得出,Compaction的目標是:
回收空間:回收過期數據的存儲空間
降低版本鏈:(RocksDB的版本鏈就是L0的文件 + 多層的查找方式《待確認》)
Compaction的原則:
控制寫入放大:
有目的的合併:減少版本鏈
可回收數據的標識:
RocksDB Compaction 成本分析(逐層緩存,Batch合併):
寫入放大:
從L1到L2層的Compaction開始分析:
每層的存儲,從範圍上幾乎是相當的,不同的是每層的數據量。因此造成了即每層單位數據量能夠覆蓋的數據範圍是逐層下降的。從層上來看,密度是逐層上升的,即最後一層密度是100%。倒數第二次,密度是10%。
逐層緩存:RocksDB利用這個特徵,可以保證數據下層過程中,每層的寫放大都是10 +1。因爲Ln層單位數據量覆蓋的數據範圍是Ln+1層的10倍,因此需要10個Ln+1層的數據塊纔可以滿足Ln層的數據範圍。所以是10 + 1。
所以總的寫入放大是 4 + 11 (n-1),在2TB-3TB這個量級的數據量下,n=5
因此RocksDB的寫入放大:
- 在update場景,寫入放大很低,因爲分層結構天生支持冷熱分離。寫入放大是37,可以按n=4計算。
- 在Insert場景,寫入放大可能更低,對於主鍵這種遞增插入的話,寫入放大很低了,不涉及到合併。在Batch基礎上可以做到個位數。對於二級索引這種隨機插入的方式,由於二級索引本身數據量就較少,按照全量250GB計算,也是在37左右。
- 所以整體來看,RocksDB的寫入放大在40左右,或者40以內。
同時由於數據存儲有較好的空間冷熱屬性(至少相對於寫操作是這樣),因此在空間回收過程中更有針對性。
有目的的合併:
通過數據有序,有目的的合併,減少邏輯Page上的版本鏈。
BwTree(LLAMA) 合併成本分析(這個可能不準):
由於論文在GC部分描述不清楚,且沒有開放源碼,所以首先描述我認爲的問題、解決方案以及根據解決方案計算的寫放大。
存在的問題:
- 內存版本鏈長度,降低CPU開銷。---這個還好,RocksDB也存在內存鏈的訪問,具體是在計算BloomFilter的時候需要訪問。所以這個不是太大,比如在7-8以內都還可以。
- 存儲上的版本鏈長度,導致讀IO較高。--- 這裏RocksDB是通過布隆過濾器實現1%的誤判,來減少讀IO的可能。
- 空間回收的IO成本,它的空間是日誌這種數據搬遷的方式,沒有天生實現冷熱分離。
解決方案:
- merge delta record:內存中根據鏈表長度定期Merge
- 將merge後的,新生成的delta record 持久化,減少磁盤上版本鏈的長度。降低IO開銷(會增加部分寫放大)。
======================================================
如果換成熱點數據的10%的增量數據的話,實際上也不會有很大空間。大概百分之一?1TB大概有10GB?
感覺BwTree的問題在於IO不可控上,相比RocksDB,可以通過BloomFilter和BLockIndex,來保證命中率。降低IO次數。
同時,合併和Append Update-D是互斥的。
可以存在這樣的策略:每個update-D同時記錄鏈表長度,從某個鏈表節點就可以知道deltalink長度。
目的性差一些,存儲都是無序的。這塊也可以參考CF搞成關係性強一些的存儲方案。但對於某一個表還是無序的。
因爲目的性較差,所以在Merge Base和Delta鏈時,開銷會高一些。
整體來看:
縮減版本鏈的寫放大是在10 = 1 + 1(4個delta merge一次) + 10 = 12
空間清理寫放大好像會多一些:
爲了讀取某個delta需要把周邊的都讀上來。
<未完>