目前在 ClickHouse 中,按照特点可以将表引擎大致分成 6 个系列,分别是合并树、外部存储、内存、文件、接口和其他。其中最为核心的当属 MergeTree 系列。
1.1 MergeTree
MergeTree 作为家族最基础的表引擎,提供了数据分区、一级索引和二级索引等功能。本节进一步介绍 MergeTree 独有的两项能力——数据 TTL 与存储策略。
1.1.1 数据 TTL
TTL 即 Time To Live,表示数据的存活时间。可以为某个列字段或整张表设置 TTL。
TTL time_col + INTERVAL 3 DAY
TTL time_col + INTERVAL 1 MONTHINTERVAL 完整的操作包括:SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER 和 YEAR。
1. 列级别 TTL
在定义表字段时声明 TTL 表达式,主键字段不能被声明 TTL:
CREATE TABLE ttl_table_v1 (
id String,
create_time DateTime,
code String TTL create_time + INTERVAL 10 SECOND,
type UInt8 TTL create_time + INTERVAL 10 SECOND
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(create_time)
ORDER BY id;写入测试数据后,10 秒执行 OPTIMIZE 强制触发 TTL 清理:
OPTIMIZE TABLE ttl_table_v1 FINAL;过期的列数据会被还原为默认值。修改列字段 TTL:
ALTER TABLE ttl_table_v1 MODIFY COLUMN code String TTL create_time + INTERVAL 1 DAY;2. 表级别 TTL
CREATE TABLE ttl_table_v2 (
id String,
create_time DateTime,
code String TTL create_time + INTERVAL 1 MINUTE,
type UInt8
) ENGINE = MergeTree
PARTITION BY toYYYYMM(create_time)
ORDER BY create_time
TTL create_time + INTERVAL 1 DAY;修改表级 TTL:
ALTER TABLE ttl_table_v2 MODIFY TTL create_time + INTERVAL 3 DAY;3. TTL 的运行机理
MergeTree 以分区目录为单位,通过 ttl.txt 文件记录过期时间。写入数据时生成 ttl.txt,分区合并时触发 TTL 删除逻辑。
小贴士:
TTL 默认合并频率由
merge_with_ttl_timeout控制,默认 86400 秒强制触发:
OPTIMIZE TABLE table_name FINAL全局启停:
SYSTEM STOP/START TTL MERGES
1.1.2 多路径存储策略
MergeTree 实现了自定义存储策略的功能。
三类存储策略:
| 策略 | 适用场景 | 说明 |
|---|---|---|
| 默认策略 | 单磁盘 | 所有分区写入 path 指定路径 |
| JBOD 策略 | 多磁盘无 RAID | 轮询写入各磁盘 |
| HOT/COLD 策略 | 不同类型磁盘 | 热数据 SSD,冷数据 HDD |
存储配置在 config.xml 中:
<storage_configuration>
<disks>
<disk_name_a>
<path>/chbase/data</path>
<keep_free_space_bytes>1073741824</keep_free_space_bytes>
</disk_name_a>
<disk_name_b>
<path>/chbase/hotdata1</path>
</disk_name_b>
</disks>
<policies>
<policie_name_a>
<volumes>
<volume_name_a>
<disk>disk_name_a</disk>
<disk>disk_name_b</disk>
<max_data_part_size_bytes>1073741824</max_data_part_size_bytes>
</volume_name_a>
</volumes>
<move_factor>0.2</move_factor>
</policie_name_a>
</policies>
</storage_configuration>JBOD 策略示例
<policies>
<default_jbod>
<volumes>
<jbod>
<disk>disk_hot1</disk>
<disk>disk_hot2</disk>
</jbod>
</volumes>
</default_jbod>
</policies>CREATE TABLE jbod_table (id UInt64)
ENGINE = MergeTree()
ORDER BY id
SETTINGS storage_policy = 'default_jbod';HOT/COLD 策略示例
<policies>
<moving_from_hot_to_cold>
<volumes>
<hot>
<disk>disk_hot1</disk>
<max_data_part_size_bytes>1073741824</max_data_part_size_bytes>
</hot>
<cold>
<disk>disk_cold</disk>
</cold>
</volumes>
<move_factor>0.2</move_factor>
</moving_from_hot_to_cold>
</policies>移动分区:
ALTER TABLE hot_cold_table MOVE PART 'all_1_2_1' TO DISK 'disk_hot1';
ALTER TABLE hot_cold_table MOVE PART 'all_1_2_1' TO VOLUME 'cold';1.2 ReplacingMergeTree
支持数据去重。使用 ORDER BY 排序键作为判断重复数据的依据。
CREATE TABLE replace_table (
id String,
code String,
create_time DateTime
) ENGINE = ReplacingMergeTree()
PARTITION BY toYYYYMM(create_time)
ORDER BY (id, code)
PRIMARY KEY id;带版本号:
ENGINE = ReplacingMergeTree(create_time)
-- 保留同一组中 create_time 最大的那一行核心逻辑:
使用 ORDER BY 排序键作为判断重复数据的唯一键
只有在合并分区时才触发删除重复数据
以数据分区为单位删除重复数据(跨分区无法去重)
无 ver:保留最后一行;有 ver:保留 ver 值最大的行
1.3 SummingMergeTree
按照预先定义的条件在合并时自动聚合汇总数据,将同一分组下的多行合并为一行。
CREATE TABLE summing_table (
id String,
city String,
v1 UInt32,
v2 Float64,
create_time DateTime
) ENGINE = SummingMergeTree()
PARTITION BY toYYYYMM(create_time)
ORDER BY (id, city)
PRIMARY KEY id;可以指定汇总列:SummingMergeTree((v1, v2)),不指定则汇总所有非主键数值类型字段。
核心逻辑:
ORDER BY 作为聚合 Key
合并分区时触发汇总
同一分区内相同聚合 Key 的数据合并为一行
非汇总字段取第一行数据
支持嵌套类型,列名需以 Map 后缀结尾
1.4 AggregatingMergeTree
MergeTree 家族中定义方式最特殊的一个,通常作为物化视图的表引擎。使用 AggregateFunction 数据类型以二进制格式存储中间聚合状态。
CREATE TABLE agg_table (
id String,
city String,
code AggregateFunction(uniq, String),
value AggregateFunction(sum, UInt32),
create_time DateTime
) ENGINE = AggregatingMergeTree()
PARTITION BY toYYYYMM(create_time)
ORDER BY (id, city)
PRIMARY KEY id;写入数据(使用 *State 函数):
INSERT INTO TABLE agg_table
SELECT 'A000', 'wuhan',
uniqState('code1'),
sumState(toUInt32(100)),
'2019-08-10 17:00:00';查询数据(使用 *Merge 函数):
SELECT id, city, uniqMerge(code), sumMerge(value)
FROM agg_table
GROUP BY id, city;配合物化视图使用(主流用法):
-- 底表(MergeTree)
CREATE TABLE agg_table_basic (
id String, city String, code String, value UInt32
) ENGINE = MergeTree()
PARTITION BY city
ORDER BY (id, city);
-- 物化视图(AggregatingMergeTree)
CREATE MATERIALIZED VIEW agg_view
ENGINE = AggregatingMergeTree()
PARTITION BY city
ORDER BY (id, city)
AS SELECT
id, city,
uniqState(code) AS code,
sumState(value) AS value
FROM agg_table_basic
GROUP BY id, city;1.5 CollapsingMergeTree
通过以增代删的思路支持行级数据修改和删除。使用 sign 标记位:sign=1 表示有效数据,sign=-1 表示需要删除的数据。
CREATE TABLE collapse_table (
id String,
code Int32,
create_time DateTime,
sign Int8
) ENGINE = CollapsingMergeTree(sign)
PARTITION BY toYYYYMM(create_time)
ORDER BY id;修改数据(三笔操作):
-- 原数据
INSERT INTO collapse_table VALUES ('A000', 100, '2019-02-20 00:00:00', 1);
-- 镜像数据(折叠删除)
INSERT INTO collapse_table VALUES ('A000', 100, '2019-02-20 00:00:00', -1);
-- 新数据
INSERT INTO collapse_table VALUES ('A000', 120, '2019-02-20 00:00:00', 1);折叠规则:
sign=1 比 sign=-1 多一行 → 保留最后一行 sign=1
sign=-1 比 sign=1 多一行 → 保留第一行 sign=-1
一样多且最后一行是 sign=1 → 保留首尾各一行
一样多且最后一行是 sign=-1 → 全部删除
注意事项:
折叠不是实时的,只在分区合并时触发
查询时需改写:
SELECT id, SUM(code * sign), COUNT(code * sign)
FROM collapse_table
GROUP BY id
HAVING SUM(sign) > 0;对写入顺序有严格要求:必须先写 sign=1 再写 sign=-1
1.6 VersionedCollapsingMergeTree
CollapsingMergeTree 的升级版,对数据写入顺序没有要求。额外指定 ver 版本号字段:
CREATE TABLE ver_collapse_table (
id String,
code Int32,
create_time DateTime,
sign Int8,
ver UInt8
) ENGINE = VersionedCollapsingMergeTree(sign, ver)
PARTITION BY toYYYYMM(create_time)
ORDER BY id;版本号字段 ver 自动追加到 ORDER BY 末端(ORDER BY id, ver DESC),保证折叠时回到正确顺序。
1.7 各种 MergeTree 之间的关系总结
1.7.1 继承关系
MergeTree 向下派生出 6 个变种表引擎,共 7 种。它们共用一个主体,在触发 Merge 动作时调用各自独有的合并逻辑。
1.7.2 组合关系
给 7 种 MergeTree 加上 Replicated 前缀,又能组合出 7 种支持副本协同的表引擎。
ReplicatedMergeTree与普通的MergeTree有什么区别呢?
上图中的虚线框部分是MergeTree的能力边界,而ReplicatedMergeTree在MergeTree能力的基础之上增加了分布式协同的能力,其借助ZooKeeper的消息日志广播功能,实现了副本实例之间的数据同步功能。
1.8 小结
MergeTree 表引擎系列:
| 引擎 | 特性 |
|---|---|
| MergeTree | 基础引擎 + TTL + 多路径存储 |
| ReplacingMergeTree | 数据去重(按 ORDER BY,分区内有效) |
| SummingMergeTree | 自动聚合 SUM |
| AggregatingMergeTree | 预聚合计算(配合物化视图) |
| CollapsingMergeTree | 以增代删(对写入顺序有要求) |
| VersionedCollapsingMergeTree | 以增代删(支持任意写入顺序) |
| Replicated* |
0 条评论