ClickHouse表引擎MergeTree介绍
1. MergeTree系列表引擎概述
MergeTree表引擎凭支持主键索引、数据分区、数据副本、数据采样和alter操作等能力。而其家族表引擎系列在其他能力上各有所长,使其系列表引擎可适用于生产环境大多数场景。
2. MergeTree介绍
2.1 MergeTree的创建方式
创建MergeTree数据表的语法如下:
CREATE TABLE [IF NOT EXISTS] [db_name.]table_name(
name1 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
name2 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
...
)ENGINE = MergeTree()
[PARTITION BY expr]
[ORDER BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[SETTINGS name=value,...]
- PARTITION BY [选填]:分区键,分区可以使用单个列字段,也可以通过元组的形式指定多个列字段,也是支持表达式。默认ClickHouse会生成一个名为all的分区,有效减少扫描范围
- ORDER BY [选填]:排序键,默认主键和排序键相同。排序键可以是单个列字段,可以通过元组的形式指定多个列字段,优先顺序按照位置先后排序
- PRIMARY KEY [选填]:主键,主键字段会产生索引,可以加快表查询。注意MergeTree允许主键重复(ReplacingMergeTree可以去重)。
- SAMPLE BY [选填]:抽样表达式。主键的配置也需要声明同样的表达式,抽样表达式需要配合SAMPLE子查询使用。
- SETTINGS:index_granularity[选填]:表示索引的粒度,默认值8192,表示每间隔8192行数据才生成一条索引
- SETTINGS:index_granularity_bytes[选填]:根据每一批次写入数据的体量大小,动态划分间隔大小,而数据的体量大小,是由这个参数控制的,默认10M。
- SETTINGS:enable_mixed_granularit_parts[选填]: 设置是否开启自适应索引间隔的功能,默认开启。
- SETTINGS:merge_with_ttl_timeout[选填]:选择性的让某个列或者表设置自动过期时间
- SETTINGS:storage_policy[选填]:MergeTree提供多路径存储策略
2.2 MergeTree的存储结构
数据存储目录data目录下:
进入对应的数据库
手动合并分区
Optimize table database_name.table_name final;
可以看出202001_1_1_0合并成为202001_1_1_1,202002_2_2_0合并成为2020_2_2_1,
202003_3_3_0、202003_4_4_0、202003_5_5_0合并为202003_3_5_1
进入分区目录
所以可以看出一张表的物理存储结构分为三个层级:表目录、分区目录、数据文件
- txt: 校验文件,用于快速校验文件的完整性和正确性
- txt: 列信息文件
- txt: 记录当前数据分区下数据的总行数
- primary_inx: 一级索引文件,存放稀疏索引
- [column_name].bin: 数据文件,使用了压缩格式存储,默认LZ4压缩格式,用于存储某一列的数据
- [column_name].mrk: 列字段标记文件。通过稀疏索引(idx)找到数据的偏移量信息(.mrk),通过偏移量直接从.bin文件中读取数据
- [column_name].mrk2: 使用了自适应大小的索引间隔,标记文件会以.mrk2命名。
- dat与minmax_[column_name].idx: partiton.dat用于保存当前分区下分区表达式最终生成的值。minmax_[column_name].idx记录了当前分区下分区字段对应原始数据的最大和最小值。
- skp_idx_[column_name].idx与skp_idx_[column_name].mrk: 如果在建表语句中声明了二级索引,则会生成二级索引与标记文件。这些索引的最终目的与一级稀疏索引相同,都是为了减少所需扫描的数据范围,以加速整个查询过程
2.3 MergeTree的数据分区
数据是以分区目录形式进行组织的,每个分区独立存储。在进行数据查询的时候,可以有效地跳过无用的数据文件。
2.3.1 数据分区规则
MergeTree数据分区规则由分区id决定的,而分区id是由分区键取值决定的。
通过元组的方式使用多个分区字段,分区id同样按照对应规则生成,不同id之间通过”-”符合按照依次顺序拼接。
例如:
PARTITION BY (length(name),toMMYY(time))
则分区id如下:
1-201905
1-201906
2.3.2 分区目录命名规则
- PartitionID:分区id
- MinBlockNum和MaxBlockNum:BlockNum是一个整数的自增长编号。编号从1开始,当插入数据的时候,数据会按照分区创建新的分区文件,每创建一个分区,分区目录这两个编号就会累加1。每次插入数据,都会生成新的分区目录,这两个编号取值相同。
- Level: 合并的次数,初始值0
2.3.3 分区目录的合并过程
MergeTree的分区目录实在数据写入的过程被创建的。当每次插入数据,都会生成新的分区目录,也就是说同一个分区,也会存在多个分区目录共存的情况。只有在后面主动或者自动进行合并成新的目录。旧的分区目录不再是激活状态,并且不会被立即删除,会经过某段时间(默认8min)。
合并目录名称的变化过程如下:
2.3.4 下图是分区创建、合并到删除的过程
- 点赞
- 收藏
- 关注作者
评论(0)