说明
是最强大的 ClickHouse 表引擎
该系列中的引擎设计用于将大量数据插入表中
国内文档 链接
主要特点:
- 基于分区键(partitioning key)的数据分区分块存储
- 数据索引排序(基于primary key和order by)
- 支持数据复制(带Replicated前缀的表引擎)
- 支持数据抽样
缺点
主键没有唯一约束,即:允许插入主键相同的数据
这里如果需要去重,可以使用 ReplacingMergeTree引擎
创建表
语法
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' [, ...] ]
[WHERE conditions]
[GROUP BY key_expr [SET v1 = aggr_func(v1) [, v2 = aggr_func(v2) ...]] ] ]
[SETTINGS name=value, ...]
解释
ENGINE— 引擎的名称和参数
ORDER BY— 排序字段
列名或任意表达式。例:ORDER BY (CounterID, EventDate)
如果没有定义主键,则使用排序字段作为主键。因为排序字段的值可以重复,所以 主键 也可以重复PARTITION BY— 分区字段,查询时避免全表扫描。可选
如果某列是Date类型(年月日),要按月分区,需要使用表达式格式化,如:toYYYYMM(date_column),该列的结果是YYYYMM格式PRIMARY KEY— 可选。默认情况下,主键与排序字段相同(所以 不具备唯一性),当与分区字段不同时,可指定。更多解释见 链接
例子
create table t_student_mt
(
sid UInt32,
name String,
age int,
`height` UInt32,
create_time Datetime
)
engine = MergeTree
partition by toYYYYMMDD(create_time)
PRIMARY KEY (sid)
order by (sid,age)
解释:
- 根据
create_time的 年月日分区 - 注解时 sid,注意:可以不唯一
- 按照 sid、age 排序
插入数据
insert into t_student_mt values
(1,'lucy',22,170,'2022-01-02 09:30:00'),
(4,'lili',22,171,'2022-01-02 09:50:00'),
(4,'张三',21,171,'2022-01-02 09:50:00'),
(2,'韩梅梅',19,165,'2022-01-01 09:30:00'),
(2,'李雷',20,182,'2022-01-01 09:30:00');
注意: 李雷、韩梅梅 的主键时相同的,也能够插入成功
clickhouse客户端查询
打开客户端:
clickhouse-client -m
查询:
select * from t_student_mt
执行结果如下(分区与分区之间是乱序,分区内是有序的):
Query id: dfd1f18c-bd90-4f48-9bea-c60e34ae396c
┌─sid─┬─name───┬─age─┬─heigth─┬─────────create_time─┐
│ 2 │ 韩梅梅 │ 19 │ 165 │ 2022-01-01 09:30:00 │
│ 2 │ 李雷 │ 20 │ 182 │ 2022-01-01 09:30:00 │
└─────┴────────┴─────┴────────┴─────────────────────┘
┌─sid─┬─name─┬─age─┬─heigth─┬─────────create_time─┐
│ 1 │ lucy │ 22 │ 170 │ 2022-01-02 09:30:00 │
│ 4 │ 张三 │ 21 │ 171 │ 2022-01-02 09:50:00 │
│ 4 │ lili │ 22 │ 171 │ 2022-01-02 09:50:00 │
└─────┴──────┴─────┴────────┴─────────────────────┘
4 rows in set. Elapsed: 0.003 sec.
问题:为什么分成2个部分
是因为根据 create_time 的 年月日 分区
注意:在 DBeaver 查询时,看不到该效果
问题:为什么主键可以重复
在 clickhouse 中,主键可以重复
问题:为什么不按照 sid、age 排序
因为是分区内排序,根据 create_time 的 年月日 分为2个区:
- 第一个区是
2022-01-01,该区内,按照 sid 排序;当 sid相同时,按照 age 排序 - 第二个区是
2022-01-02,该区内,按照 sid 排序;当 sid相同时,按照 age 排序