4.2.7 cstore
列存储格式是OLAP类数据库系统最常用的数据格式,适合复杂查询、范围统计类查询的在线分析型处理系统。本节主要介绍openGauss数据库内核中cstore列存储格式的实现方式。
1. cstore整体框架
cstore列存储格式整体框架如图4-21所示。其主要模块代码分布参见4.2.1节。与行存储格式不同,cstore列存储的主体数据文件以CU为I/O单元,只支持追加写操作,因此cstore只有读共享缓冲区。CU间和CU内的可见性由对应的CUDESE表(astore表)决定,因此其可见性和并发控制原理与行存储astore基本相同。
图4-21 cstore列存储格式整体框架示意图
2. cstore存储单元结构
图4-22 CU结构示意图
如图4-22所述,cstore的存储单元是CU,分别包括以下内容。
(1) CU的CRC值,为CU结构中除CRC成员之外,其他所有字节计算出的32位CRC值。
(2) CU的magic值,为插入CU的事务号。
(3) CU的属性值,为16位标志值,包括CU是否包含NULL行、CU使用的压缩算法等CU粒度属性信息。
(4) 压缩后NULL值位图长度,如果属性值中标识该CU包含NULL行,则本CU在实际数据内容开始处包含NULL值位图,此处储存该位图的字节长度,如果该CU不包含NULL行,则无该成员。
(5) 压缩前数据长度,即CU数据内容在压缩前的字节长度,用于读取CU时进行内存申请和校验。
(6) 压缩后数据长度,即CU数据内容在压缩后的字节长度,用于插入CU时进行内存申请和校验。
(7) 压缩后NULL值位图内容,如果属性值中标识该CU包含NULL行,则该成员即为每行的NULL值位图,否则无该成员。
(8) 压缩后数据内容,即实际写入磁盘的CU主体数据内容。
每个CU最多保存对应字段的MAX_BATCH_ROWS行(默认60000行)数据。相邻CU之间按8kB对齐。
CU模块提供的主要CU操作接口如表4-28所示。
表4-28 CU操作接口
函数名称 | 接口含义 |
AppendCuData | 向组装的CU中增加一行(仅对应字段) |
Compress | 压缩(若需)和组装CU |
FillCompressBufHeader | 填充CU头部 |
CompressNullBitmapIfNeed | 压缩NULL值位图 |
CompressData | 压缩CU数据 |
CUDataEncrypt | 加密CU数据 |
ToVector | 将CU数据解构为向量数组结构 |
UnCompress | 解压(若需)和解析CU |
UnCompressHeader | 解析CU头部内容 |
UnCompressNullBitmapIfNeed | 解压NULL值位图 |
UnCompressData | 解压CU数据 |
CUDataDecrypt | 解密CU数据 |
3. cstore多版本机制
cstore支持完整事务语义的DML查询,原理如下。
(1) CU间的可见性:每个CU对应CUDESC表(astore行存储表)中的一行记录(一对一),该CU的可见性完全取决于该行记录的可见性。
(2) 同一个CU内不同行的可见性:每个CU的内部可见性对应CUDESC表中的一行(多对一),该行的bitmap字段为最长MAX_BATCH_ROWS个bit的删除位图(bit 1表示删除,bit 0表示未删除),通过该位图记录的可见性和多版本,来支持CU内不同行的可见性。同时由于DML操作都是行粒度操作的,因此对于行号范围相同的、不同字段的多个CU均对应同一行位图记录。
(3) CU文件读写并发控制:CU文件自身为APPEND-ONLY,只在追加时对文件大小扩展进行加锁互斥,无须其他并发控制机制。
(4) 同一个字段的不同CU,对应严格单调递增的cu_id编号,存储在对应的CUDESC表记录中,该cu_id的获取通过图4-24中的文件扩展锁来进行并发控制。
(5) 对于cstore表的单条插入以及更新操作,提供与每个cstore表对应的delta表(astore行存储表),来接收单条插入或单条更新的元组,以降低CU文件的碎片化。
可见,cstore表的可见性依赖于对应CUDESC表中记录的可见性。一个CUDESC表的结构如表4-29所示,其与CU的对应关系如图4-23所示。
表4-29 CUDESC表的结构
字段名 | 类型 | 含义 |
col_id | integer | 字段序号,即该cstore列存储表的第几个字段;特殊的,对于CU位图记录,该字段恒为-10 |
cu_id | oid | CU序号,即该列的第几个CU |
min | text | 该CU中该字段的最小值 |
max | text | 该CU中该字段的最大值 |
row_count | integer | 该CU中的行数 |
cu_mode | integer | CU模式 |
size | bigint | 该CU大小 |
cu_pointer | text | 该CU偏移(8k对齐);特殊的,对于CU位图记录,该字段为删除位图的二进制内容 |
magic | integer | 该CU magic号,与CU头部的magic相同,校验用 |
extra | text | 预留字段 |