数据ClickHouse(九):MergeTree系列表引擎之ReplacingMergeTree

网友投稿 731 2022-12-01

大数据ClickHouse(九):MergeTree系列表引擎之ReplacingMergeTree

大数据ClickHouse(九):MergeTree系列表引擎之ReplacingMergeTree

文章目录

​​MergeTree系列表引擎之ReplacingMergeTree​​

​​一、ReplacingMergeTree基本讲解​​

​​二、使用ReplacingMergeTree是需要注意以下几点​​

​​三、测试实例​​

​​1、测试去重按照Order by 字段进行去重,而不是按照primary 主键字段进行去重​​

​​2、测试不指定[ver]列时,插入相同排序字段的数据,保留最新一条数据​​

​​3、测试指定[ver]列时,插入相同排序字段的数据,保留当前[ver]列最大值​​

​​4、测试不同分区中有相同的Order by 字段时,不去重​​

MergeTree系列表引擎之ReplacingMergeTree

一、ReplacingMergeTree基本讲解

以上MergeTree不能对相同主键的数据进行去重,ClickHouse提供了ReplacingMergeTree引擎,可以针对同分区内相同主键的数据进行去重,它能够在合并分区时删除重复的数据。值得注意的是,ReplacingMergeTree只是在一定程度上解决了数据重复问题,由于自动分区合并机制在后台定时执行,所以并不能完全保障数据不重复。ReplacingMergeTree 适用于在后台清除重复的数据以节省空间。

ReplaceingMergeTree建表语句:

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2], ...) ENGINE = ReplacingMergeTree([ver])[PARTITION BY expr][ORDER BY expr][SAMPLE BY expr][SETTINGS name=value, ...]

以上建表语句的解释如下:

[ver] :可选参数,指定列的版本,可以是UInt*、Date或者DateTime类型的字段作为版本号。该参数决定了数据去重的方式。当没有指定[ver]时,保留最后插入的数据,也就是最新的数据;如果指定了具体的[ver]列,则保留最大版本数据。

二、使用ReplacingMergeTree是需要注意以下几点

如何判断数据重复

ReplacingMergeTree在去除重复数据时,是以ORDERBY排序键为基准的,而不是PRIMARY KEY。

何时删除重复数据

在执行分区合并时,会触发删除重复数据。optimize的合并操作是在后台执行的,无法预测具体执行时间点,除非是手动执行。

不同分区的重复数据不会被去重

ReplacingMergeTree是以分区为单位删除重复数据的。只有在相同的数据分区内重复的数据才可以被删除,而不同数据分区之间的重复数据依然不能被剔除。

数据去重的策略是什么

如果没有设置[ver]版本号,则保留同一组重复数据中的最新插入的数据;如果设置了[ver]版本号,则保留同一组重复数据中ver字段取值最大的那一行。

optimize命令使用

一般在数据量比较大的情况,尽量不要使用该命令。因为在海量数据场景下,执行optimize要消耗大量时间。

三、测试实例

1、测试去重按照Order by 字段进行去重,而不是按照primary 主键字段进行去重

#创建表 t_replacing_mt ,使用ReplacingMergeTree引擎node1 :) create table t_replacing_mt(:-] id UInt8,:-] name String,:-] age UInt8,:-] gender String:-] ) engine = ReplacingMergeTree():-] order by (id,age):-] primary key id:-] partition by gender;#向表 t_replacing_mt 中插入以下数据:node1 :) insert into t_replacing_mt values (1,'张三',18,'男'),:-] (2,'李四',19,'女'),:-] (3,'王五',20,'男');#查询表 t_replacing_mt 中的数据:node1 :) select * from t_replacing_mt;┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└───┴────┴────┴──────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└───┴────┴────┴──────┘#向表 t_replacing_mt 中插入id 为1的一行数据node1 :) insert into t_replacing_mt values (1,'张三',10,'男');#查询表 t_replacing_mt 数据:node1 :) select * from t_replacing_mt;┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 10 │ 男 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└────┴──────┴─────┴────────┘#执行 optimize命令手动合并分区数据node1 :) optimize table t_replacing_mt;#查询表 t_replacing_mt 数据,发现没有按照primary key 去重。node1 :) select * from t_replacing_mt;┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 10 │ 男 ││ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└────┴──────┴─────┴────────┘#再次向表 t_replacing_mt 插入数据:node1 :) insert into t_replacing_mt values (1,'张三三',18,'男');#查询表 t_replacing_mt 数据node1 :) select * from t_replacing_mt;┌─id─┬─name───┬─age─┬─gender─┐│ 1 │ 张三三 │ 18 │ 男 │└───┴──────┴────┴──────┘┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└───┴────┴────┴──────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 10 │ 男 ││ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└───┴─────┴───┴──────┘#再次执行 optimize命令手动合并分区数据node1 :) optimize table t_replacing_mt;#查询表 t_replacing_mt 数据node1 :) select * from t_replacing_mt;┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└───┴────┴────┴──────┘┌─id─┬─name───┬─age─┬─gender─┐│ 1 │ 张三 │ 10 │ 男 ││ 1 │ 张三三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└───┴──────┴────┴─────┘

注意:通过以上测试发现ClickHouse ReplacingMergeTree中去除重复数据时,是以ORDERBY排序键为基准的,而不是PRIMARY KEY。

2、测试不指定[ver]列时,插入相同排序字段的数据,保留最新一条数据

#删除表 t_replacing_mt 重建,使用ReplacingMergeTree引擎node1 :) create table t_replacing_mt(:-] id UInt8,:-] name String,:-] age UInt8,:-] gender String:-] ) engine = ReplacingMergeTree():-] order by id:-] primary key id:-] partition by gender;#向表 t_replacing_mt 中插入以下数据node1 :) insert into t_replacing_mt values (1,'张三',18,'男'),:-] (2,'李四',19,'女'),:-] (3,'王五',20,'男');#查询表 t_replacing_mt 中的数据node1 :) select * from t_replacing_mt ;┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└────┴──────┴─────┴────────┘#向表 t_replacing_mt 中插入排序字段相同的一行数据node1 :) insert into t_replacing_mt values (1,'张三',10,'男');#查询表 t_replacing_mt 中的数据node1 :) select * from t_replacing_mt;┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 10 │ 男 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │ └────┴──────┴─────┴────────┘#执行 optimize命令手动合并分区数据node1 :) optimize table t_replacing_mt;#查询表 t_replacing_mt 中的数据node1 :) select * from t_replacing_mt;┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 10 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└────┴──────┴─────┴────────┘

注意:通过以上测试可以发现,ClickHouse ReplacingMergeTree中不指定[ver]列时,当插入排序字段相同的数据时,保留最新一条数据。

3、测试指定[ver]列时,插入相同排序字段的数据,保留当前[ver]列最大值

#删除表 t_replacing_mt 重新创建,使用ReplacingMergeTree引擎,指定[ver]node1 :) create table t_replacing_mt(:-] id UInt8,:-] name String,:-] age UInt8,:-] gender String:-] ) engine = ReplacingMergeTree(age):-] order by id:-] primary key id:-] partition by gender;#向表 t_replacing_mt 中插入数据:node1 :) insert into t_replacing_mt values (1,'张三',18,'男'),:-] (2,'李四',19,'女'),:-] (3,'王五',20,'男');#查询表 t_replacing_mt中数据:node1 :) select * from t_replacing_mt ;┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└────┴──────┴─────┴────────┘#向表 t_replacing_mt 中插入排序字段相同的一行数据node1 :) insert into t_replacing_mt values (1,'张三',10,'男');#查看表 t_replacing_mt中的数据node1 :) select * from t_replacing_mt;┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 10 │ 男 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└────┴──────┴─────┴────────┘#对表 t_replacing_mt中的数据执行手动分区合并node1 :) optimize table t_replacing_mt;#查看表 t_replacing_mt中的数据node1 :) select * from t_replacing_mt;┌─id─┬─name─┬─age─┬─gender─┐│ 2 │ 李四 │ 19 │ 女 │└────┴──────┴─────┴────────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└────┴──────┴─────┴────────┘

注意:通过以上测试可以发现,在ClickHouse中创建ReplacingMergeTree时,如果指定了[ver]列,当存在Order by字段重复时,会保留ver列最大值对应的行。

4、测试不同分区中有相同的Order by 字段时,不去重

#删除表 t_replacing_mt ,重新创建node1 :) create table t_replacing_mt(:-] id UInt8,:-] name String,:-] age UInt8,:-] gender String:-] ) engine = ReplacingMergeTree():-] order by id:-] primary key id:-] partition by gender;#向表 t_replacing_mt 中插入以下数据:node1 :) insert into t_replacing_mt values (1,'张三',18,'男'),:-] (2,'李四',19,'女'),:-] (3,'王五',20,'男');#再次向表 t_replacing_mt 中插入以下数据:node1 :) insert into t_replacing_mt values (1,'张三三',10,'女');#对表 t_replacing_mt中的数据执行手动分区合并node1 :) optimize table t_replacing_mt;#查看表中的数据node1 :) select * from t_replacing_mt;┌─id─┬─name───┬─age─┬─gender─┐│ 1 │ 张三三 │ 10 │ 女 ││ 2 │ 李四 │ 19 │ 女 │└───┴──────┴────┴─────┘┌─id─┬─name─┬─age─┬─gender─┐│ 1 │ 张三 │ 18 │ 男 ││ 3 │ 王五 │ 20 │ 男 │└───┴────┴────┴─────┘

注意:通过以上测试可以发现,在ClickHouse中创建ReplacingMergeTree时,不同分区中相同的Order by 字段不会去重。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringACK对RabbitMQ消息的确认(消费)
下一篇:分布式电源对配电网故障定位的影响(Python代码实现)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~