跳转至

列存储引擎

列存储引擎说明

本节主要介绍SeaboxMPP列存储相关概念及使用方式、建议应用场景等内容。

什么是列存储

传统的关系型数据库,如 Oracle、DB2、MySQL、SQL SERVER 等采用行式存储法(Row-based),在基于行式存储的数据库中, 数据是按照行数据为基础逻辑存储单元进行存储的, 一行中的数据在存储介质中以连续存储形式存在。通常OLTP类应用使用行存储较多。

列存储(Column-based)是相对于行存储来说的, Greenplum、GaussDB 等分布式数据库均采用列式存储。在基于列式存储的数据库中, 数据是按照列为基础逻辑存储单元进行存储的,一列中的数据在存储介质中以连续存储形式存在。通常OLAP类应用使用列存储较多,特点是对实时性要求不高,但处理的数据量大,通常应用于复杂的动态报表系统上。

行存储与列存储相关对比见下表:

列存储 行存储
优点 批量写入效率高,压缩比高,复杂分析查询效率高。少量列的select、join、 group等IO少,性能好。适用于向量计算。 小数据量频繁DML效率较好。精确查询效率高。Select * 查询所有列的操作性能好
缺点 高并发小数据量的事务操作效率相对较低。Select * 投影列数量多的时候效率较低 大数据量写效率低。数据压缩比低。复杂查询(join、group、order)效率低
改进 增加行存缓冲,优化小数据量事务操作。

列存储基本存储机制见下图,每列都是独立存储(独立文件),按列访问数据文件IO效率最优:

列存储基本存储机制

列存基本使用方法

SeaboxMPP数据库支持创建表时使用不同方式指定,具体方式如下:

  • 使用using scolumn关键字创建,示例如下:
create table t1(a int,b varchar(20)) using scolumn;
  • 使用with子句创建,示例如下:
create table t1(a int,b varchar(20)) with(orientation=column);
  • 设置参数,默认建表使用列存储,示例如下:
set default_table_access_method = scolumn; --设置建表默认为列存表
create table t1(a int,b varchar(20));

列存表的其他大部分操作和普通行存表类似,也支持例如索引、视图(物化视图)、分区表等,语法相同。

如:

  • 删除表
drop table t1;
  • 清除表数据
truncate table t1;
  • 清理表数据
vacuum t1;
vacuum full t1;
  • 修改表结构
alter table t1 add column c float default 1.2;
alter table t1 add column a;
  • 事务基本操作
Begin;
Insert into t1 values(1,aaa);
Update t1 set b=bbb where a=1;
Commit;

列存储常用参数

scolumn_store_sort : 存储时是否排序(当前是块内排序),默认排序,对性能有一定影响,追求入库性能的话可以关闭排序

列存支持的压缩算法

SeaboxMPP数据库表为列存储时支持多种压缩算法,支持的压缩算法见下表:

压缩算法关键字 说明
NONE 不使用压缩;
AUTO 列存表默认的压缩算法,根据入库数据特征自行判断适用的算法;
LZ4 相对于其他压缩算法,优势在于压缩、解压速度都很快;
RLE 对重复数据有较高的压缩效果;
ZSTD 通用压缩算法,具有良好的压缩比,支持压缩等级1~20级,默认为1;
Gorilla 一种偏好时序数据的压缩算法;
Multiple T64+ZSTD的压缩组合,针对时序数据有天然的高压缩比优势。

创建表时可通过以下方式指定压缩算法:

  1. 指定全局级压缩算法(server重启后生效)

    alter system set sc_default_storage_options=compresstype=none; 
    

    重启server后建表,则列存表为压缩类型为none

    create table test (a int, b varchar(20)) with (orientation=column);
    
  2. 支持指定某个数据库的压缩算法(新连接生效)

    alter database test set sc_default_storage_options=compresstype=zstd;
    

    重连接server后建表,则列存表的压缩类型为指定的ZSTD。

    create table test (a int, b varchar(20)) with (orientation=column);
    
  3. 支持当前session建表时的默认压缩算法

    set sc_default_storage_options=compresstype=multiple;
    

    建列存表,压缩类型为指定的multiple。

    create table test (a int, b varchar(20)) with ( orientation=column);
    
  4. 支持指定表级压缩算法

    create table t1(a int, b varchar(20)) with (orientation=column, compresstype=zstd, compresslevel=5);
    
  5. 支持指定列级压缩算法

    create table t1(a int encoding (compresstype=gorilla), b varchar(20)) with (orientation=column);
    

列存扩展功能

稀疏索引功能

对没有索引的表或表的非索引列作为条件进行查询时,顺序SCAN过程会将条件列的所有数据都读取一遍,如果数据量很大的话,会造成比较重的IO负载。而稀疏索引利用块的统计信息,能够在不读取数据文件的情况下,排除掉不满足查询条件的块或者提前判断出全满足查询条件的块,能够有效的减少此种场景下的IO和运算,提升查询效率。稀疏索引的维护和使用对用户透明。

SeaboxMPP数据库稀疏索引存储示意见下图:

稀疏索引存储

SeaboxMPP数据库稀疏索引使用示意见下图:

稀疏索引使用

稀疏索引功能相关参数

scolumn_rough_index_enable
查询是否使用稀疏索引开关。on,查询使用稀疏索引;off,查询不使用稀疏索引。默认值为on。
scolumn_rough_index_in_method_threshold
稀疏索引判断in条件选择使用何种方法的阈值(in判断有两种方法)。取值为整型值,默认值为5。in条件中值的个数不超过阈值时,使用第一种方法(将in条件中的值逐个使用等值条件判断,此方法建议在in条件中值较少时使用,过滤准确率较高);in条件中值的个数超过阈值使用第二种方法(只使用in条件中的最大最小值判断,此方法建议在in条件中值的个数较多时使用,可能会有将ALL或NONE判断为SOME的情况,但是执行效率较高)。实现细节参见设计文档。
scolumn_rough_index_use_level
稀疏索引使用控制参数: 1,数值类型使用稀疏索引;2,数值和字符串类型都使用稀疏索引。默认值为2。
scolumn_rough_index_build_level
控制入库时是否维护稀疏索引。0,不维护;1,只维护数值型;2,维护数值型和字符串型。默认值为2。

列存表cache功能

列存表cache功能介绍

当列存表在小数据量频繁入库时,尤其是列数比较多的场景,需要频繁进行小IO处理,此时磁盘性能成为数据入库的瓶颈,如使用列存储又无法使用列存储针对大数据量查询以及压缩存储的需求。针对这样的场景,SeaboxMPP数据库实现了列存表cache功能,通过使用该功能,上述场景性能提升约数倍到数十倍。

其功能优势如下:

  • 列存表在启用行存储缓存机制后,能有效提高列存本身的小批量数据写入性能

  • 小批量写入、入库首先会将数据写入缓存表

  • 当满足一定条件后,再由后台线程将缓存表中的数据转换到列存表,此过程对用户透明

列存表cache功能实现机制见下图:

列存表cache功能内部机制

针对上述场景,模拟的测试用例如下:

  • 每秒加载一批数据,每批数据248条

  • 每批数据约2.2MB,单行950个字段

  • 持续运行4小时数

直接使用行存储与使用行存表cache功能的性能对比如下图:

小批量写入性能对比测试

使用列存表cache功能的相关语法:

  • 列存表增加heap缓存
alter table t1 add table for cache;
  • heap缓存表中的数据强制刷入列存表

alter table t1 refresh table for cache;
* 删除heap缓存表

alter table t1 drop table for cache;

列存表cache功能使用涉及以下2个参数:

scolumn_heap_cache_option
行存缓冲的使用方式,取值:off,数据直接入列存;All,所有数据全部入行存缓冲; not-full,整block数据入列存,不满block的数据入行存缓冲
scolumn_row_to_block_threshold
后台进程转列存存储的阈值,超过该值会触发转存动作。默认为32768,即列存表block的默认条数作为触发条件(大部分情况不需要调整,除非期望行存缓冲来缓存更多数据)

数据透明加密

透明数据加密(TDE)是指数据在写到磁盘上时对其进行加密,当读取数据进行解密,文件在硬盘上是密文,在内存中是明文。如下图所示:

存储加密架构示意图

透明存储加密使用方式:

  • 使用数据库的透明存储加密需要打开开关enable_tde,透明存储加密分为软加密和硬加密两种方式,配置方式如下:

  • 软加密(密钥管理及加密过程通过软件实现)

    • 配置参数
    ENABLE_HARD_ENCRYPT = OFF
    
    • 创建主密钥
    CREATE MASTER ENCRYPTION KEY BY PASSWORD 'password';
    
    • 加载主密钥

    LOAD MASTER ENCRYPTION KEY BY PASSWORD 'password';
    
    * 硬加密(密钥管理及加密过程通过外置加密卡实现)

    • 安装并配置好加密卡

    • 配置参数

    ENABLE_HARD_ENCRYPT = ON
    
  • 表级加密

软加密和硬加密的语法相同

  • 建表

    CREATE TABLE table_name ... WITH (ENABLE_TDE = ON, ENCRYPTION_NAME = '***' );
    
  • 切换加密表的加密开关

    -- 打开
    ALTER TABLE table_name SET (ENABLE_TDE = OFF);
    -- 关闭
    ALTER TABLE table_name SET (ENABLE_TDE = OFF);
    
  • 删除表级数据加密密钥

    DROP DATA ENCRYPTION KEY FOR table_name;
    
  • 使用约束

    • 不支持sequence加密,不支持系统表加密

    • 表的加密算法指定后不支持更改

    • 若建表时未开启加密功能,后续无法再转换为加密表

    • 列存表暂不支持切换加密开关

列存表设置block中数据条数

SeaboxMPP数据库列存表按照一定行数组成一个block存储,该行数默认为32768,支持建表时指定该值。少数场景调整该值可能会获取更好的压缩比或IO效率。

具体使用方式如下:

create table tab(a int) with(orientation=column,blockrownum=65536);

列存表设置排序block数和排序列

SeaboxMPP数据库列存表按照指定的排序block数和排序列进行排序。

  • 根据数据的特征选择合适的排序列以及排序block数,能够提高数据的压缩比以及查询性能

  • 当排序block数为1时,加载性能与修改之前保持一致;当排序block数大于1时,加载性能会下降,下降的幅度与排序block数以及排序列相关。

列存表排序涉及的参数:

  • block_sort_cnt(排序block数)以及order_columns(排序列),创建列存表时进行指定。

  • 其中order_columns指定列名为排序列, 最大可指定8个排序列。

  • block_sort_cnt默认为0, 最小值为0, 最大值为32768,与blockrownum配合使用,可以决定排序的数据行数。

  • block_sort_count(全局变量指定排序block数)

实现原理与架构:

  • 当全局变量block_sort_count > 0时,

  • 若创建列存表时指定排序block数,则在插入数据时根据指定的排序block数进行排序,否则按照默认的排序block数进行排序。

  • 若创建列存表时指定排序列,则在插入数据时根据指定的列进行排序,否则按照自评估的列进行排序。

  • 列存表支持指定block数和列排序的具体工作流程如下图所示,其中blockcnttosort代表指定的排序block数,partial_sort_blocks代表处理的累计block。

排序工作流程图

  • 当全局变量block_sort_count = 0时,

  • 若创建列存表时只指定排序列,则排序block数默认为128。

  • 如创建列存表时只指定排序block数,则排序列默认为自评估的排序列。

  • 如列存表没有指定排序列和排序block数,则该表不排序。

列存表排序功能使用

  • 创建列存表指定排序列和排序block数
  CREATE TABLE t1_sort(id INT, name TEXT) WITH (ORIENTATION = COLUMN, block_sort_cnt = 2) order_columns (name,id);
  • 列存表增加/删除排序列
  CREATE TABLE t1_sort(id INT, name TEXT) WITH (ORIENTATION = COLUMN);
  ALTER TABLE t1_sort ADD order_columns (name, id);
  ALTER TABLE t1_sort DROP order_columns;
  • 设置列存表排序的block数
  set block_sort_count = 128;

列存表VACUUM快速模式

VACUUM快速模式,是一种专门针对列存表的VACUUM性能优化模式,前提是支持列存表数据文件分裂功能。 其在VACUUM原有普通模式的基础上,将压缩阶段替换为新的回收阶段,不再进行数据的读写操作,而是直接以分裂文件为单位进行清理

VACUUM快速模式的回收阶段,根据列存表的元数据信息判定某个分裂文件是否满足清空条件,也即当分裂文件中的所有数据都被delete时,该文件被直接清空,即使列存表中包含大量数据,也可以高效完成VACUUM过程,达到快速释放磁盘空间的目的。

VACUUM快速模式应用场景为:

  • 列存表在大范围连续地Delete行的情况下,快速模式可以高效回收磁盘空间;

  • 在Delete行不连续或行数较小的情况下,快速模式的回收效果不佳,可以切换普通模式进行清理回收。

列存VACUUM快速模式涉及的参数

  • vacuum_scolumn_fast_mode: 全局变量,实现VACUUM快速模式和普通模式的切换。

列存VACUUM快速模式使用方法:

  • 当 set vacuum_scolumn_fast_mode = true,且待清理表为列存表时,VACUUM触发快速模式

 set vacuum_scolumn_fast_mode = true;
VACUUM [ ( option [, ...] ) ] [ table [, ...] ]
* 当 set vacuum_scolumn_fast_mode = true,待清理表为行存表时,VACUUM仍触发普通模式

  • 当 set vacuum_scolumn_fast_mode = false; 无论待清理表为什么类型,VACUUM均触发普通模式