点一下关注吧!!!非常感谢!!持续更新!!!
目前已经更新到了:
- Hadoop(已更完)
- HDFS(已更完)
- MapReduce(已更完)
- Hive(已更完)
- Flume(已更完)
- Sqoop(已更完)
- Zookeeper(已更完)
- HBase(已更完)
- Redis (已更完)
- Kafka(已更完)
- Spark(已更完)
- Flink(已更完)
- ClickHouse(正在更新···)
章节内容
上节我们完成了如下的内容:
- MergeTree 存储结构
- MergeTree 数据标记
- MergeTree 分区 索引 标记 压缩协同
ReplacingMergeTree
简介
这个引擎是在MergeTree的基础上,添加了处理重复数据的功能,该引擎和MergeTree的不同之处在于它会删除具有相同主键的重复项。
特点
- 使用ORDER BY排序键作为判断重复的唯一键
- 数据的去重只会在合并的过程中触发
- 以数据分区为单位删除重复数据,不同分区的重复数据不会被删除
- 找到重复数据的方式依赖数据已经ORDER BY排好顺序了
- 如果没有ver版本号,则保留重复数据的最后一行
- 如果设置ver版本号,则保留重复数据中ver版本号最大的数据
案例
创建新表
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;
运行结果如下图所示:
插入数据
INSERT INTO replace_table VALUES ('A001', 'C1', '2024-08-01 08:00:00');
INSERT INTO replace_table VALUES ('A001', 'C1', '2024-08-02 08:00:00');
INSERT INTO replace_table VALUES ('A001', 'C8', '2024-08-03 08:00:00');
INSERT INTO replace_table VALUES ('A001', 'C9', '2024-08-04 08:00:00');
INSERT INTO replace_table VALUES ('A002', 'C2', '2024-08-05 08:00:00');
INSERT INTO replace_table VALUES ('A003', 'C3', '2024-08-06 08:00:00');
运行结果如下所示:
optimize
首先说一下,optimize的作用是:
- 合并数据块:ClickHouse是一个列式的数据库,它的数据是以数据块(parts)的形式存储在磁盘上,OPTIMIZE TABLE 语句通过较小的数据块来减少块的数量,从而提高查询性能和磁盘利用率。
- 删除标记的行:如果表中有被标记为删除的行,这些行将在优化过程中被真正删除,释放相应的空间。
- 分区管理:可以对表的指定分区进行优化,以减少分区内的碎片。
SELECT
*
FROM
replace_table;
运行结果如下图所示,通过观察,去重是根据ORDER BY来的,并非 PRIMARY KEY:
继续插入一条数据:
INSERT INTO replace_table VALUES('A001', 'c1', '2024-01-01 08:00:00')
执行结果如下所示:
观察上图可以看出,不同分区的数据不会去重。
SummingMergeTree
简介
该引擎来自MergeTree,区别在于,当合并SummingMergeTree表的数据片段时,ClickHouse会把所有具有相同聚合数据的条件KEY的行合并为一行,该行包含了被合并的行中具有数值数据类型的列的汇总值。
如果聚合数据的条件KEY的组合方式使得单个键值对应于大量的行,则可以显著减少存储空间并加快数据查询的速度。对于不可加的列,会取一个最先出现的值。
特点
- 用ORDER BY排序键作为聚合数据的条件KEY
- 合并分区的时候触发汇总逻辑
- 以数据分区为单位聚合数据,不同分区的数据不会被汇总
- 如果在定义引擎时指定了Columns汇总列(非主键)则SUM汇总这些字段
- 如果没有指定,则汇总所有非主键的数值类型字段
- SUM汇总相同的聚合KEY的数据,依赖ORDER BY排序
- 同一分区的SUM汇总过程,非汇总字段的数据保留第一行取值
- 支持嵌套结构,但列字段名称必须以Map后缀结束
案例1
创建新表
CREATE TABLE smt_table (
date Date,
name String,
a UInt16,
b UInt16
) ENGINE = SummingMergeTree(date, (date, name), 8192, (a));
运行的结果如下图所示:
插入数据
insert into smt_table (date, name, a, b) values ('2024-08-10', 'a', 1, 2);
insert into smt_table (date, name, a, b) values ('2024-08-10', 'b', 2, 1);
insert into smt_table (date, name, a, b) values ('2024-08-11', 'b', 3, 8);
insert into smt_table (date, name, a, b) values ('2024-08-11', 'b', 3, 8);
insert into smt_table (date, name, a, b) values ('2024-08-11', 'a', 3, 1);
insert into smt_table (date, name, a, b) values ('2024-08-12', 'c', 1, 3);
运行结果如下所示:
optimize
等待一段时间,或者手动 optimize table 来触发合并,再查询信息:
OPTIMIZE TABLE smt_table;
SELECT
*
FROM
smt_table;
执行结果如下图所示:
通过观察,我们会发现,2024-08-11, b 和 a 列合并相加了,b列取了8(因为b列为8的数据最先插入的)
案例2
创建新表
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);
执行结果如下图:
插入数据
insert into table summing_table values('A000','beijing',10,20,'2024-08-20 08:00:00');
insert into table summing_table values('A000','beijing',20,30,'2024-08-30 08:00:00');
insert into table summing_table values('A000','shanghai',10,20,'2024-08-20 08:00:00');
insert into table summing_table values('A000','beijing',10,20,'2024-06-20 08:00:00');
insert into table summing_table values('A001','beijing',50,60,'2024-02-20 08:00:00');
执行结果如下图所示:
optimize
OPTIMIZE TABLE summing_table;
SELECT
*
FROM
summing_table;
执行结果如下图所示:
通过观察,根据ORDER BY排序键(id, city)作为聚合KEY,因为没有在建表时指定SummingMergeTree的SUM列,所以把所有非主键数值类型的列都进行了SUM处理。
案例3
SummingMergeTree支持嵌套类型的字段,但列字段名称必须以Map后缀结束。
创建新表
CREATE TABLE summing_table_nested(
id String,
nestMap Nested(
id UInt32,
key UInt32,
val UInt64
),
create_time DateTime
) ENGINE = SummingMergeTree()
PARTITION BY toYYYYMM(create_time)
ORDER BY id;
执行的结果如下图所示:
插入数据
INSERT INTO summing_table_nested VALUES ('1', [101, 102], [201, 202], [1001, 1002], '2024-08-01 10:00:00');
INSERT INTO summing_table_nested VALUES ('2', [103, 104], [203, 204], [1003, 1004], '2024-08-01 10:00:00');
INSERT INTO summing_table_nested VALUES ('1', [105, 106], [205, 206], [1005, 1006], '2024-08-01 10:00:00');
INSERT INTO summing_table_nested VALUES ('2', [107, 108], [207, 208], [1007, 1008], '2024-08-02 10:00:00');
INSERT INTO summing_table_nested VALUES ('3', [109, 110], [209, 210], [1009, 1010], '2024-08-02 10:00:00');
INSERT INTO summing_table_nested VALUES ('4', [111, 112], [211, 212], [1011, 1012], '2024-08-02 10:00:00');
执行过程如下图所示:
执行过程如下图所示:
可以看到,我们插入了6条数据,但是查询到的只有4条,而且此外也进行计算的SUM处理。