本文简要从存储结构、索引结构和数据更新方式等几个方面介绍当前比较热门的OLAT/HATP列式存储引擎,包括ClickHouse和SqlServer。
- ClickHouse
1.1 存储结构和索引结构
ClickHouse拥有多种表引擎类型,在这众多的表引擎中,MergeTree是比较有代表性的引擎之一,被广泛使用。MergeTree采用列式存储,类似LSM Tree的架构组织数据。数据导入时被划分为多个Part,每个Part对应一个目录。Part中包含各个列的数据,每个列都有独立的文件。后台会调度合并任务,将多个小的Part合并成更大的Part,类似LSM Tree的合并过程。Part中包含几类文件:
-
数据文件(.bin),每一列的数据都分别存储在数据文件,一般以主键排序。数据文件中划分为若干个Block,Block是列存文件的压缩单元。每个Block又会包含若干个索引Granularity,用于索引定位。
一个压缩数据块由头信息和压缩数据两部分组成。头信息固定使用9位字节表示,具体由1个UInt8(1字节)和2个UInt32(4字节)整型组成,分别代表了使用的压缩算法类型、压缩后的数据大小和压缩前的数据大小。
-
索引文件(.idx),索引文件又分为主键索引和二级索引:
MergeTree的主键索引与传统数据库的主键索引有所不同,MergeTree的主键索引只负责排序,但是不会去重。主键索引文件中,存储的是每一个Granularity中起始行的主键值,可以在扫描过程中过滤部分Granularity。
MergeTree的二级索引文件中可以存储Granularity的minmax、set、bloom_filter、ngrambf_v1等信息。
- Mark文件(.mrk),由于索引文件是对Granularity进行索引,类似于逻辑索引。Mark文件记录Granularity在数据文件中的物理偏移,类似于将逻辑索引转换成物理索引。
1.2 数据更新方式
MergeTree对于批量导入支持较好,对OLTP级事务更新仅有限支持。MergeTree存储引擎对数据实时可见要求非常高的场景是不太友好的。
- SqlServer
2.1 存储结构和索引结构
SQL Server从SQL Server 2012开始涉及AP场景,当初只是提供了Read-Only Columnstore Index。从SQL Server 2016开始,SQL Server引入了三方面的改进,本文主要分析基于In-memory OLTP Hekaton的列存索引这一个方面。在SQL Server Hekaton中,列存是作为行存的索引存在,也就是说可以针对行存中的部分列做列存索引。因此,在做OLTP行存事务处理时,数据也会实时同步更新到列存中。对于列存索引,也是分为增量部分和基线部分。数据插入列存时,首先进入增量部分,后台会根据数据的冷热程度(数据更新的频繁程度),将冷数据合并到基线部分,而热数据会留在增量部分。基线部分数据采用行列混合存储形式,每个Row Group作为一个压缩单元,Row Group内是列式存储。数据在从增量部分合并到基线部分时会分配RowID,通过RowID可以做基线数据的逻辑删除操作。
基于Hekaton的列存索引
2.2 数据更新方式
与Hekaton的行存使用相同的日志实时做事务处理,使用MVCC实现事务隔离。
整体对比
参考文献
[1] ClickHouse
【https://clickhouse.tech/】
[2] Real-time analytical processing with SQL server
【https://dl.acm.org/doi/10.14778/2824032.2824071】