ClickHouse MergeTree 结构
MergeTree 是 ClickHouse 中非常重要的存储引擎。它本身由许多概念组成,逐层分解如下图所示:
Table
ClickHouse 作为 OLAP 关系型数据库,本身有 表 的概念。表 在 ClickHouse 的磁盘上就是一个文件夹,但 表 归属于一个 database(也是一个文件夹),也就是在一个 database 文件夹下。
比如 /var/lib/clickhouse/data/system/metric_log
就是在 system
这个 database 下的 metric_log
这张表。
Partition
在 ClickHouse 中,Partition 是逻辑上的分区概念,并不存在物理表示。
数据插入时会根据 DDL 中的 PARTITION BY
(分区表达式)将数据强制切分,然后再拆分为不同的 Part。
Part
在 ClickHouse 中,一个 Part 就是 ClickHouse 磁盘上的一个文件夹,在表文件夹下。比如 /var/lib/clickhouse/data/system/metric_log/202303_1_491_98
就是 system.metric_log
这张表的一个 Part。
Part 内的数据是有序的(按照 DDL 的 ORDER BY
排序),每个 Part 实际存储数据、索引。ClickHouse 后台会不断合并不同的 Part。Part 的命名规则为 {PARTITION 名}_{最小的 Block 序号}_{最大的 Block 序号}_{层级}
。[1]
Part 存储格式有三种:
- IN MEMORY
- COMPACT
- WIDE
WIDE Part 内会包含如下文件:
checksums.txt
:校验和columns.txt
:记录表中各 列 名和类型count.txt
:记录本 Part 的行数default_compression_codec.txt
:数据文件(.bin
)的默认压缩算法minmax_{分区键}.idx
:分区表达式中的列在这个 Part 的最小、最大值partition.dat
:根据PARTITION BY
计算出的 Partition 数值,归属于相同 Partition 的 Part 有相同的内容primary.idx
:主键索引文件{列名}.bin
:某列的压缩数据文件{列名}.mrk1/2/3
[2]:某列压缩数据的 Block 标记文件 ,以及 Granule 标记文件skip_idx_{索引名}.idx
:跳表索引skip_idx{索引名}.mrk
:跳表索引标记文件
Column
每个 Column 在不同 Part 中都会有一个 .bin
文件存储压缩数据和一个 .mrk2
数据偏移索引。
Block
Block 有两层含义:
- 指 ClickHouse 计算时在内存中的一批数据,包含每个列名、类型和数据
- 插入数据落盘时,包含多个 Granule 的数据压缩基本单位
Block 是 ClickHouse 进行 I/O 的基本单位。读取时每次都要读取整个 Block 并解压缩,获取需要的 Granule;写入时也需要内存中的 Block 达到 min_compress_block_size
(最大值为 max_compress_block_size
)后压缩落盘。
Granule
Granule 是固定大小的一组行,一个 Granule 会在主键索引中存在一条 记录。
Granule 是 ClickHouse 中数据的最小单位,也是 I/O 的最小单位。.mrk2
文件记录了一个 .bin
中所有 Granule 的偏移量(两列,一列 Block 偏移量,和这个 Block 内每个 Granule 的偏移量),方便数据读取。