内核】MergeTree数据物理存储结构"/>
【ClickHouse内核】MergeTree数据物理存储结构
目录
概述
查看ClickHouse的数据目录
测试环境描述
数据物理存储信息
数据分区目录命名规则
结论
概述
ClickHouse是一款开源列式存储分析型数据库,它最核心的特点就是极致存储压缩率和查询性能。在ClickHouse中MergeTree存储引擎又是重中之重。那么本文主要和大家一起了解下MergeTree存储引擎实际的物理存储是什么样的。
查看ClickHouse的数据目录
查看配置文件所在路径信息
ps -ef | grep clickhouse
查看配置文件中数据目录位置信息
sudo vi /etc/clickhouse-server/config.xml
测试环境描述
创建MergeTree表引擎的SQL如下所示:
CREATE TABLE merge_tree_table
(
`partition_key` Int32,
`primary_key` Int32,
`extremum_key` Int32,
INDEX idx_extremum_key extremum_key TYPE minmax GRANULARITY 1
)
ENGINE = MergeTree()
PARTITION BY partition_key
ORDER BY primary_key
SETTINGS index_granularity = 3, min_rows_for_wide_part = 0, min_bytes_for_wide_part = 0
ClickHouse新版本有compact功能,可以提高插入量少插入频率频繁时的性能。但是底层就不会每一列都生成一个.bin文件了。只会生成一个统一的data.bin。所以我们先关闭了compact功能(min_rows_for_wide_part = 0, min_bytes_for_wide_part = 0),方便讲解。
插入数据的SQL如下所示
insert into merge_tree_table values(1,1,1);
insert into merge_tree_table values(10,2,2),(10,3,3);
insert into merge_tree_table values(5,10,4),(5,9,5),(5,8,6),(5,7,7),(5,6,8),(5,5,9),(5,4,10);
数据物理存储信息
由上图可知,目前ClickHouse中有两个数据库分别为
- default数据库
- system数据库
由上图可知,default数据库目录下存储的是表信息。
由上图可知,表信息存在如下信息
- xxx_xxxx_xx_x 数据分区目录信息
- detached目录中包含使用[DETACH]查询从表中分离的部分。
- format_version.txt 版本文件
综上所述,磁盘目录结构方式描述(树结构)
通过上图,我们可以推导出ClickHouse关于MergeTree目录层级
/data/数据库名称/表名称/数据分区目录/XXX
上面我们看到数据分区的目录命名相对不好理解,那么接下来我们看下,数据分区目录的命名规则是什么?
数据分区目录命名规则
MergeTree数据分区目录命名规则 其规则为
PartitionID_MinBlockNum_MaxBlockNum_Level
比如上面的10_2_2_0
其中 10 是分区ID ,2_2对应的是最小的数据块编号和最大的数据块编号,最后的 _0 表示目前分区合并的层级。这么命名是为了数据目录合并算法。之后的文章会进行说明。
数据目录各个字段含义解析
PartitionID:该值由 insert 数据时分区键的值来决定。分区键支持使用任何一个或者多个字段组合表达式,针对取值数据类型的不同,分区ID的生成逻辑目前有四种规则:
- 不指定分区键:如果建表时未指定分区键,则分区ID默认使用all,所有数据都被写入all分区中。
- 整型字段:如果分区键取值是整型字段,并且无法转换为YYYYMMDD的格式,则会按照该整型字段的字符形式输出,作为分区ID取值。
- 日期类型:如果分区键属于日期格式,或可以转换为YYYYMMDD格式的整型,则按照YYYYMMDD格式化后的字符形式输出,作为分区ID取值。
- 其他类型:如果使用其他类似Float、String等类型作为分区键,会通过对其插入数据的128位Hash值作为分区ID的取值。
MinBlockNum 和 MaxBlockNum: BlockNum 是一个整型的自增长型编号,该编号在单张MergeTree表中从1开始全局累加,当有新的分区目录创建后,该值就加1,对新的分区目录来讲,MinBlockNum 和 MaxBlockNum 取值相同。例如上面示例数据为10_2_2_0。但是如果当分区目录进行合并后,取值规则会发生变化, MinBlockNum 取同一分区目录中最新的 MinBlockNum值。MaxBlockNum 取同一分区内所有目录中的最大值。例如10_1_2_1。
Level: 表示合并的层级。相当于某个分区被合并的次数,它不是以表全局累加,而是以分区为单位,初始创建的分区,初始值为0,相同分区ID发生合并动作时,在相应分区内累计加1。
数据目录里面文件含义描述
- checksums.txt: 校验值文件。
- columns.txt: 列名文件,记录了表中的所有列名。
- count.txt: 计数文件,文本文件存储,用于记录当前数据分区目录下数据的总行数。
- default_compression_codec.txt: 数据文件的压缩方式。
- 【columnName】.bin: 数据文件,使用压缩格式存储,默认使用LZ4压缩格式,用于存储某一列的数据。由于MergeTree采用列式存储,每个列字段都拥有独立的bin数据文件,并以列字段命名。
- 【columnName】.mrk2: 列字段标记,使用二进制格式存储。标记文件中保存了bin文件中数据的偏移量信息,标记文件与稀疏文件对齐,又与bin文件一一对应,所以MergeTree通过标记文件建立了primary.idx稀疏索引与bin数据文件的隐射关系。
- minmax_partition_key.idx、partition.dat 若使用了分区键则会额外生成partition.dat和minmax索引文件,均使用二进制格式存储。partition.dat用于保存当前分区下分区表达式最终生成值,minmax索引文件用于记录当前分区字段对应原始数据的最小值和最大值。在分区索引作用下,进行数据查询时候能够快速跳过不必要的数据分区目录,从而减少最终需要扫描的数据范围。
- primary.idx: 以及索引文件,使用二进制格式存储。用于存放稀疏索引, 借助稀疏索引在数据查询的时候能够排除主键范围之外的数据文件,从而减少数据扫描范围,加速查询速度。
- skp_idx_idx_extremum_key.idx、skp_idx_idx_extremum_key.mrk2: 若在创建表语句中声明了二级索引则会额外生成相应的二级索引与标记文件,他们同样用二进制存储。二级索引在clickhouse中又称之为跳数索引,目前拥有minmax,set,ngrambf_v1和tokenbf_v1四种类型。这些索引的目标和一级稀疏索引相同,为了进一步减少所需要扫描的数据范围,以加速整个查询过程。
结论
数据库中的数据一定是要落地的,不可能一直存储到内存中。所以数据库最终都会把数据回写到磁盘,来满足存储和索引目的。ClickHouse查询性能很卓越一部分也是借助了磁盘上面构造的这些文件。
那么ClickHouse如何通过这些文件来达到高性能查询的目的的,在后续文章中会进行阐述。
更多推荐
【ClickHouse内核】MergeTree数据物理存储结构
发布评论