前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >大数据ClickHouse(九):MergeTree系列表引擎之ReplacingMergeTree

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

原创
作者头像
Lansonli
发布2022-08-25 03:57:54
1.5K0
发布2022-08-25 03:57:54
举报
文章被收录于专栏:Lansonli技术博客Lansonli技术博客

MergeTree系列表引擎之ReplacingMergeTree

一、ReplacingMergeTree基本讲解

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

  • ReplaceingMergeTree建表语句:
代码语言:javascript
复制
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 主键字段进行去重

代码语言:javascript
复制
#创建表 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]列时,插入相同排序字段的数据,保留最新一条数据

代码语言:javascript
复制
#删除表 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]列最大值

代码语言:javascript
复制
#删除表 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 字段时,不去重

代码语言:javascript
复制
#删除表 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 字段不会去重。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ​MergeTree系列表引擎之ReplacingMergeTree
    • 一、ReplacingMergeTree基本讲解
      • 二、使用ReplacingMergeTree是需要注意以下几点
        • 三、测试实例
          • 1、测试去重按照Order by 字段进行去重,而不是按照primary 主键字段进行去重
          • 2、测试不指定[ver]列时,插入相同排序字段的数据,保留最新一条数据
          • 3、测试指定[ver]列时,插入相同排序字段的数据,保留当前[ver]列最大值
          • 4、测试不同分区中有相同的Order by 字段时,不去重
      相关产品与服务
      大数据处理套件 TBDS
      腾讯大数据处理套件(Tencent Big Data Suite,TBDS)依托腾讯多年海量数据处理经验,基于云原生技术和泛 Hadoop 生态开源技术对外提供的可靠、安全、易用的大数据处理平台。 TBDS可在公有云、私有云、非云化环境,根据不同数据处理需求组合合适的存算分析组件,包括 Hive、Spark、HBase、Flink、presto、Iceberg、Alluxio 等,以快速构建企业级数据湖、数据仓库。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档