數據膨脹了?你的數倉又沒有空間了?

摘要:爲了解決數據膨脹,GaussDB(DWS)通過vacuum和FSM來清理和重用物理空間。本文簡單介紹FSM的設計和原理,並通過一個例子對FSM功能進行簡單的測試和驗證。

本文分享自華爲雲社區《數據膨脹了?又沒有空間了?一招教你解決》,原文作者:QWERT886 。

數據膨脹,指的是物理數據文件的大小明顯高於實際存儲的數據量。甚至某些特殊場景下,一個表中只有一條簡單的數據,但是表對應的物理文件可能已經達到M級甚至G級。

爲了解決數據膨脹,GaussDB(DWS)通過vacuum和FSM來清理和重用物理空間。本文簡單介紹FSM的設計和原理,並通過一個例子對FSM功能進行簡單的測試和驗證。

數據膨脹的原因

想弄清楚數據膨脹的原因,首先要了解GaussDB(DWS)行存表數據基於MVCC的存儲機制

  1. INSERT很簡單,就是將元組插入到頁面的空閒空間中;
  2. DELETE則是將元組標記爲舊版本,但是即使這個舊版本對所有事務都不可見了,這個元組佔用的空間也不會歸還給文件系統;
  3. UPDATE相當於DELETE+INSERT,等於是佔用了兩條元組的位置,類似DELETE,舊版本的元組依然佔用着物理空間。

很明顯,在一通增刪改操作之後,頁面上的舊版本元組勢必是佔有一定比重的。這就導致了物理文件大小明顯高於實際的數據量。

設計方案

爲了解決無效元組佔用空間的問題,GaussDB(DWS)提供了vacuum功能,在舊版本元組過期(對所有事務都不可見)後,vacuum可以將元組物理刪除,這樣頁面上被清理出來的空閒空間就可以被再次使用了。

但是每個頁面的空閒空間又不是固定大小的,所以如果要利用這些空間空間,就需要遍歷一遍數據頁面來找到它們,但是這樣會造成比較大的開銷。因此就設計了用來記錄每個頁面剩餘空間的空閒空間映射表FSM(Free Space Mapping),以便高效的將空閒空間管理起來,方便查找和重新使用。

實現過程

FSM是以 _fsm 爲後綴的文件對外展現的,每個行存表都有一個fsm文件。在表創建時,fsm文件並不會一起創建出來,而是在第一次vacuum時纔會被創建。

因爲不同頁面上的元組長度各不相同,爲了快速高效的管理空閒空間,沒必要非常精確的管理每一個字節。將一個8K的數據頁面(data block)分成256份,從頁面頭到頁面尾順序計算,排除頁面頭等固定支出,最多可以有255份空閒空間,這樣FSM用1個Byte就可以標識出一個數據頁面的空閒空間的大小。

在空閒空間查詢時,我們只需要找到能滿足需求的頁面即可,所以FSM將每個頁的空餘空間信息通過一個大根堆結構進行維護。這樣只需要從堆的根獲取當前最大的剩餘空間就可以知道有沒有能符合要求的頁面。堆中的每個葉子節點都對應一個數據頁,葉子節點上記錄的是數據頁的可用單元的個數。

然後FSM機制通過在不同的FSM頁間維護了一個類似FSM本身的樹形結構,來管理所有的FSM block:一個3層的多叉樹結構。

FSM頁面也是大小爲8K的塊(FSM block),所以每個FSM block最多可以描述4096個數據頁面(粗略計算,肯定是達不到的,因爲有頁頭等信息)。按照3層計算:4096(0層)4096(1層)(8k*4096)(2層) = 2PB。可以管理2PB的數據,這對描述一張行存表,完全夠用了。

整個FSM機制如下圖:

image.png

  1. level root和level medium都是用來查找level 2中的FSM頁面的
  2. level bottom是用來查找符合要求的heap頁面的

FSM信息的可視化讀取

FSM查找和維護的邏輯並不複雜,但是整個過程對外是不可見的。因此GaussDB(DWS)提供了pagehack工具來讀取FSM文件,幫助查看當前數據頁的空閒空間情況。下面結合pagehack工具解析FSM文件進一步理解FSM機制:

初始化數據

  1. 首先新建行存表並插入大量數據。分佈列數據固定,爲了讓數據都落入一個dn,方便後面分析。
  2. 刪掉 2 條位於第一個heap page的數據。因爲是新建的表,所以數據會從前往後順序的落到數據頁面裏,c2等於1和2的兩條數據一定在第一個頁面上。
create table t1(c1 int, c2 int);   -- 建行存表
insert into t1 values(15, generate_series(1,100000000)); -- 插入數據
delete from t1 where c2= 1 and c2=2; --刪掉 2 條位於第一個heap page的數據。

生成FSM文件並落盤

vacuum t1; -- 生成FSM文件
checkpoint; -- 刷盤

用pagehack解析FSM文件

1、pagehack 解析FSM文件並輸出到文件中

pagehack -t fsm -f 73916_fsm > 73916_fsm.lo

 

2、打開文件,從第一個fsm block開始看。第一個fsm block屬於 level root,看到一共111個fsm block,下層的最大空閒空間是31,且在數組0的位置上 image.png

3、接着看到第二個fsm block,屬於level medium,記錄的最大空閒空間爲31,數組0位置代表下層的fsm block 0有2個slot,數組108位置代表fsm block 108 有31個slot,其他都是0。0~108中間的0表示沒有這些頁面都沒有空閒空間了,108之後的表示頁面還沒有擴展出來 image.png

4、再往後面是第三個fsm block,這個及以後的block都屬於level bottom,這層的FSM頁面都是直接對應數據頁面的。可以看到最大剩餘空間爲2,數組0位置代表heap page 0 有2個位置,正好是剛纔刪除的兩條數據。

image.png

5、第4個及後面的一直到110的block的信息如下,可以看到整個heap page都沒有剩餘空間了,這是因爲這些頁面一直在插入,沒有刪除數據。 image.png

6、第111個block顯示,最大空閒空間爲31。FSM總塊111個,塊號110,減去前面的兩個非葉子層的block,爲108,正好對應前面第二個block中的第108個slot(存31)。
image.png
從12553這行開始算,到12628的第26個位置爲31,(12628-12553)40+26 = 3026。用page range算:439452+3026 = 442478。按 8k 頁面算: 4424788192 = 3,624,779,776
image.png
image.png
看一下實際文件大小:1073741824*3+403554304 = 3,624,779,776,與剛纔算的結果相同 image.png

思考總結

總結剛纔的測試:

  1. 我們一開始向空表順序插入了大量的數據,頁面也是順序的擴展
  2. 在442478頁面的時候,最後的數據插入完畢,並且還留有31個空間可用
  3. 當我們從第一個頁面刪除了兩條數據後,第一個頁面空餘出了2個空間
  4. fsm樹的樣子類似:
      fsm block 0
             (31,0,0...0/
         fsm block 1
         (2,0,0...0,31,0...0)
          / 
    fsm block 2 fsm block 110
    (2,0,0...0) (0,0...0,31,0...0
  5. 在level bottom這層的fsm block中,按順序存放的就是heap block的空閒空間值。
  6. 1億條數據用了108個slot,而一個fsm block 有4000+個葉子,所以肯定是用不完的。

對於日常運維的建議是:

打開autovacuum,讓GaussDB(DWS)自動的幫你做vacuum,這樣新的數據就可以通過FSM機制複用空閒頁面,以減少數據膨脹帶來的磁盤空間浪費。

想了解GuassDB(DWS)更多信息,歡迎微信搜索“GaussDB DWS”關注微信公衆號,和您分享最新最全的PB級數倉黑科技~

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

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