目录
openGauss 数据库 SQL 引擎
openGauss 数据库执行器技术
openGauss 存储技术
一、openGauss 存储概览
二、openGauss 行存储引擎
三、openGauss 列存储引擎
Ⅰ、列存储引擎的总体架构
Ⅱ、列存储的页面组织构造
Ⅲ、列存储的 MVCC 设计
IV、 列存储的索引设计
V、 列存储自适应压缩
VI、 列存储的长久化设计
四、openGauss 内存引擎
openGauss 事务机制
openGauss 数据库安全
openGauss 存储技术
三.openGauss 列存储引擎
列存的索引设计
04
列存反对的索引设计有:
§ Btree 索引
§ 稠密索引
§ 聚簇索引
- 列存的 Btree 索引
列存储引擎在 Btree 索引的反对角度,与传统的行存储引擎无实质差异。对于个别用于应答大数据批量剖析性负载的列存储引擎来说,Btree 索引有助于帮忙列存储大大晋升本身的点查效率,更好的适应混合负载。
行存储相干 Btree 索引的索引页面上,存储的是[key -> ctid](键 -> ctid)的映射,在列存的场景下,这个映射仍旧为[key-> ctid],但列存储的构造并不能像行存一样,通过 ctid 中的 block number(块号)和 offset(偏移量)间接找到此行数据在数据文件页面中的地位。列存储 ctid 中记录的为(cu_id, offset),要通过 CUDesc 构造来进行查找。
在基于 btree 的扫描中,从索引中拿到 ctid 后,须要在对应的 CUDesc 表中,依据 CUDesc 在 cu_id 列的索引找到对应的 CUDesc 记录,并由此关上对应的 CU 文件,依据 offset 找到数据。
如果此操作设计大量的存储层性能开销,因而列存的 btree 索引,与列存的其余操作一样,对立都为批量操作。即会现依据 btree 索引找到 ctid 的汇合,而后对此汇合进行排序,再批量的对排序后的 ctid 进行 CU 文件级别的查找与操作。这样能够做到程序枯燥的索引遍历,大大减少了重复操作文件带来的 CPU 以及 IO 开销。
- 列存的稠密索引
列存储引擎每个列自带 min/max 稠密索引,每个 CUDesc 存储该 CU 的最小值和最大值。
那么在查问的时候,能够依据查问条件做简略的 min/max 判断,如果查问条件不在 (min,max) 范畴内,必定不须要读取这个 CU,能够大大地缩小 IO 读取,如图 31 所示。
图 31 稠密索引图
注:txn_info 示意事务信息;CUPtr 压缩单元的指针;CUNone 示意必定不命中;CUSome 示意可能有数据匹配;CU_Full 示意压缩单元数据全命中。
- 列存的聚簇索引
列存表在建设时能够抉择在列上建设聚簇索引(partial sort index)。
如果业务的初始数据模型较为离散,那么稠密索引不同 CU 之间的 min、max 就会有大量交加,这种状况下在给定谓词对列存表进行检索的过程中,会呈现大量的 CU 误读取,甚至可能导致其查问效率与全表扫描近似。如图 32 所示,查问 2 根本命中了所有 CU,min-max 索引没有可能无效筛选。
图 32 数据模型较为离散时查问效果图
聚簇索引能够对局部区间内的数据做相应的排序(个别区间会蕴含多个 CU 所笼罩的行数),能够保障 CU 之前交加尽量少,能够极大地晋升在数据离散场景下稠密索引的效率。
其示意图如图 33 和图 34 所示。
图 33 聚簇索引失效前
图 34 聚簇索引失效后
同时,聚簇索引会使得 CU 外部的数据邻近有序,晋升 CU 文件自身的压缩比以及压缩效率。
列存储自适应压缩 05
每个列自适应抉择压缩,反对 delta value encoding(差分编码)、Run length encoding(游程编码)、dictionary encoding(字典编码)、LZ4、zlib 等混合压缩。依据数据个性的不同,压缩比个别能够有 3X~20X。
列存储引擎反对低、中、高三种压缩级别,用户在创立表的时候能够指定压缩级别。
导入 1TB 原始数据量,别离测试低、中、高三种压缩级别,入库后数据大小别离是 100GB、73GB、61GB。如图 35 所示。
图 35 压缩比示意图
每次数据导入,首先对每个列数据依照向量组装,对前几批数据做采样压缩,依据数值类型和字符串类型,会抉择尝试不同的压缩算法。一旦采样压缩实现后,接下来的数据就抉择优选的压缩算法了。如图 36 所示,次要分数值压缩和字符压缩。其中对 Numeric 小数类型,会转换为整数后,再依照数值压缩。对数值型字符串,也会尝试转换为整数再依照数值压缩。
图 36 面向列的自适应压缩
列存储的长久化设计 06
下面章节列存储的组织构造在 MVCC 机制中提到,列存的存储单位由 CUDesc 和 CU 文件独特组成,其中 CUDesc 记录了 CU 相干的元信息,管制其可见性,实际上充当了一个“代理”的角色。然而 CUDesc 和 CU,本质上还是拆散的文件状态。CUDesc 表,实质上还是行存储表,其长久化流程听从行存储的共享缓冲区脏页与 Redo 日志的长久化流程,在事务提交前,CUDesc 的改变会被记录在 Redo 日志中进行长久化。单个 CU 文件自身,因为含有大量的数据,应用失常的事务日志进行长久化会须要耗费大量的事务日志,引入十分大的性能开销,并且复原也非常迟缓。因而依据其利用场景,append-only(仅容许追加)的属性,以及与 CUDesc 的对应关系,列存储的 CU 文件,为了确保 CUDesc 和 CU 长久化状态的统一,在事务提交、CUDesc 对应事务日志长久化前,会后行强制刷盘(Fsync),来确保事务改变的长久化。
因为数据库主备机例的同步也依赖事务日志,而 CU 文件并不蕴含在事务日志内,因而在与列存储同步时,主备实例之间除去失常的日志通道外,还有连贯的数据通道,用于传输列存储文件。CUDesc 的改变会通过日志进行同步,而 CU 文件则会被间接通过数据通道传输到备机实例,并通过 bit change map(BCM)文件来记录主备机例之间文件的同步状态。
未完待续 …….