閱讀533 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Greenplum列存壓縮表原理

用法

create table testao(id int, name text) with  (APPENDONLY=true, ORIENTATION=column, COMPRESSTYPE=zlib, COMPRESSLEVEL=5, BLOCKSIZE=1048576, OIDS=false)

APPENDONLY=true, ORIENTATION=column這兩個屬性決定了這是列存壓縮表。

COMPRESSTYPE: 壓縮方式,支持zlip,RTE等

COMPRESSLEVEL: 壓縮級別,0-9

BLOCKSIZE: 塊大小8kB-2MB

優勢

  1. 節約成本,列存壓縮表空間占用遠小於普通的heap表空間
  2. 對查詢涉及的列很少時候,無需去讀其他列的數據,減少IO
  3. 追加寫速度快

存儲結構

總體方法是一個文件隻存一個列的值,一個文件由多個block組成。

  1. 組成結構

每個列占用一個至多個文件,最多128個,不同列的值不會同時出現一個文件。之所以這麼設計,是為了解決並發問題。

b936cde04e6f6721.png

  1. block結構
struct getBlockInfo
{
  int32     contentLen;
  int           execBlockKind;
  int64     firstRow;   /* is expected to be -1 for pre-4.0 blocks */
  int           rowCnt;
  bool      isLarge;
  bool      isCompressed;
  }         getBlockInfo;

BLOCKSIZE大小是8kB-2MB,由壓縮前的數據大小決定,壓縮後的block大小不一,其中block header不參與壓縮。如果插入的值超過blocksize,那麼數據將會拆成多個block;對於NULL值,block中使用bit位表示。

99d721584c83b863.png

  1. RowNum機製

對於heap表,由tupleid決定每條記錄的位置(tupleid包含記錄在文件中偏移位置),而對於AO表,數據是壓縮的,沒法確定value在文件中偏移位置,因此引用了rownum,每條記錄都有自己的rownum,rownum一直增長,rownum可能不連續,但是沒關係,我們的block中記錄了起始rownum以及block在文件中偏移位置,所以隻要給我們一個rownum,我們就能定位到它所在的block,然後從block中就可以遍曆到這個rownum對應的記錄。

每次insert都會更新rownum,為了解決頻繁更新問題,每次申請100個rownum,批量insert時每100個才會更新rownum。通過select * from gp_fastsequence可以查看已使用的rownum。

並發insert原理

當多個Session同時向表中insert數據時,如果隻有一個文件,那麼每次追加都需要對文件加鎖,顯然會降低插入性能,為了解決這個問題,當有並發insert時,每個session向各自對應的文件insert數據。不過最大的並發是128,單個列不能超過128個文件限製。

3d496d92b4fb7ab3.png

update/delete實現

delete和update不會在數據文件中直接更新或者刪除,而是使用一張heap輔助表visimap,包含一個bitmap列,通過select * from pg_appendonly可以查看到,對任何一個數據的刪除直接在bitmap中標記一下即可。update是delete和insert兩步組合實現。

最後更新:2017-08-13 22:24:51

  上一篇:go  雲服務器 ECS 建站教程:ECS搭建Microsoft SharePoint 2016
  下一篇:go  怡海軟件:CRM、ERP、SCM的區別和聯係?