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两步组合实现。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值