Clickhouse之MergeTree的存储结构和分区详解

目录

 

1、MergeTree的创建方式与存储结构

1.1、MergeTree的创建方式

 

1.2、MergeTree的存储结构

2、数据分区

2.1、数据分区规则

2.2、分区目录的命令规则

2.3、分区目录的合并过程


1、MergeTree的创建方式与存储结构

1.1、MergeTree的创建方式

创建MergeTree数据表需要将ENGINE参数声明为MergeTree(),其完整的语法如下所示:

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],
    ...
    INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
    INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2
) ENGINE = MergeTree()
ORDER BY expr
[PARTITION BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...]
[SETTINGS name=value, ...]

 

  • PARTITION BY [选填]:分区键,用于指定表数据以何种标准进行分区。分区键既可以是单个列字段,也可以通过元组的形式使用多个列字段,同时它也支持使用列表达式。如果不声明分区键,则ClickHouse会生成一个名叫all的分区。合理使用数据分区,可以减少查询时文件的扫描范围。
  • ORDER BY [必填]:排序键,用于指定在一个数据片段内,数据以何种标准排序。默认情况下主键(PAIMARY KEY)与排序键相同。排序键既可以是单个列字段,也可以通过元组的形式使用多个列字段。
  • PAIMARY KEY [选填]:主键,顾名思义,声明后会按照主键生成一级索引,用于加速查询。默认情况下,主键和排序键(order by)相同,所以通常直接使用order by 代为指定主键,无须刻意通过primary key声明。在一般情况下,在单个数据片段内,数据与一级索引以相同的规则升序排列。与其他数据库不同,MergeTree主键允许存在重复数据(ReplacingMergeTree可以去重)。
  • SAMPLE BY [选填]:抽样表达式,用于声明数据是以何种标准进行采样。如果用了这个配置,那么在主键中也要声明同样的表达式。
  • SETTINGS:index_granularity [选填]: index_granularity对MergeTree是一个很重要的参数,它表示索引的粒度,默认是8192。也就是说,MergeTree的索引在默认情况下,每间隔8192行数据才生成一条索引。
  • SETTINGS:index_granularity_bytes [选填]:在19.11版本之前,clickhouse只支持固定大小的索引间隔,由index_granularity控制,默认是8192。在新版本,它增加了自适应间隔大小的特性,即根据每一批次写入数据的体量大小,动态划分间隔大小。而数据的体量大小由index_granularity_bytes控制,默认是10M(10x1024x1024),设置为0表示不启动自适应功能。
  • SETTINGS:enable_mixed_granularity_parts [选填]:设置是否开启自适应索引时间间隔的功能,默认是开启。
  • SETTINGS:merge_with_ttl_timeout [选填]:从19.6版本开始,MergeTree提供了数据TTL的功能。
  • SETTINGS:storage_policy [选填]:从19.15版本开始,MergeTree提供了多路径的存储策略。

1.2、MergeTree的存储结构

MergeTree表引擎中的数据是拥有物理存储的,数据会按照分区目录的形式保存到磁盘之上,完整的存储结构如下:

table_name

    partition_1

        checksums.txt

        columns.txt

        count.txt

        primary.idx

        [colume].bin

        [column].mrk

        [column].mrk2

        patition.dat

        minmax_[column].idx

        skp_idx_[column].idx

        skp_idx_[column].mrk

    partition_2

    partiton_n

从上面可以看出一张完整的数据表的完整物理结构为为3个层级,依次是数据表目录、分区目录及各分区下具体的数据文件。依次介绍它们的作用

(1)partition: 分区目录,余下各类数据文件(parmary.idx、[column].mrk、[colume].bin等)都是以分区目录的形式被组织存放,属于相同分区的数据,最终会被合并到同一个分区目录,而不同分区的数据,永远不会被合并在一起。

(2)checksums.txt:校验文件,使用二进制格式存储。保存了其他文件的size大小及size的哈希值,用于快速校验文件的完整性和正确性。

(3)columns.txt: 列信息文件,使用明文格式存储,用于保存此数据分区下的列字段信息。

(4)count.txt:计数文件,使用明文格式存储。用于记录当前数据分区目录下数据的总行数。

(5)primary.idx:一级索引文件,使用二进制格式存储。用于存放稀疏索引,一张MergeTree表只能声明一次一级索引。

(6)[column].bin:数据文件,使用压缩格式存储,默认为LZ4压缩格式,用于存储某一列的数据。

(7)[colume].mrk:列字段标记文件,使用二进制格式存储。标记文件中保存列.bin文件中数据的偏移量信息。标记文件与稀疏索引对齐,又与.bin文件一一对应。

(8)[column].mrk2:如果使用了自适应大小的索引间隔,则标记文件会以.mrk2命名。它的工作原理和作用与.mrk标记文件相同。

(9)partition.dat与minmax_[column].idx:如果使用了分区键,例如partition by eventtime,则会额外生成partition.dat 和minmax索引文件,它们均使用二进制格式存储。partition.dat用于保存当前分区表达式最终生成的值;而minmax索引用于记录当前分区字段对应原始数据的最小和最大值。

(10)skp_idx_[column].idx与skp_idx_[column].mrk;如果在建表语句中声明了二级索引,则会额外生成相应的二级索引与标记文件,它们同样也使用二进制存储。二级索引在clickhouse中又称为跳数索引,目前拥有minmax,set,ngrambf_v1和tokenbf_v1四种类型。

 

2、数据分区

数据是以分区目录的形式进行组织的,每个分区独立分开存储。借助这种形式,在对mergetree进行数据查询时,可以有效跳过无用的数据文件,只使用最小的分区目录子集。

2.1、数据分区规则

分区id目前有四种生成逻辑:

  1. 不指定分区键:不使用分区键,分区id默认取名all,所有数据都会被写入这个all分区。
  2. 使用整型
  3. 使用日期类型
  4. 使用其他类型:如果分区键取值既不属于整型也不属于日期类型,则通过128位hash算法取其hash值作为分区id的取值。

2.2、分区目录的命令规则

分区目录名:201905_1_1_0

201905表示分区目录的id;1_1分别表示最小的数据块编号(minblocknum)与最大的数据块编号(maxblocknum);最后的_0(level)则表示目前合并的层级。

2.3、分区目录的合并过程

201905_1_1_0

201905_2_2_0        ----->合并后  201905_1_3_1

201905_3_3_0

mergetree的分区目录并不是在数据表被创建之后就存在的,而是在数据写入过程中被创建的。也就是说如果一张表不写入任何数据,那么也不会有任何分区目录存在。

mergetree中伴随着每一批数据的写入(一次insert语句),都会生成一批新的分区目录。即使不同批次的数据属于相同分区,也会生成不同的分区目录。

clickhouse会通过后台任务再将属于相同分区的多个目录合并为一个新的目录,已经存在的旧的分区并不会立即被删除,而是在之后的某个时刻通过后台任务被删除(默认8分钟)。

新目录名称的合并规则:

minblocknum:取同一分区内所有目录中最小的minblocknum值

maxblocknum:取同一分区内所有目录中最大的maxblocknum值

level:取同一分区内最大的level值加1

                                                                 关注博主的微信公众号,其中有更多精彩文章,还有大量免费教学视频和电子书等你来拿!

                                                                                                            

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值