ClickHouse(十三):Clickhouse MergeTree系列表引擎 - ReplicingMergeTree

 进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容!

🏡个人主页:含各种IT体系技术,IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客

📌订阅:拥抱独家专题,你的订阅将点燃我的创作热情!

👍点赞:赞同优秀创作,你的点赞是对我创作最大的认可!

⭐️ 收藏:收藏原创博文,让我们一起打造IT界的荣耀与辉煌!

✏️评论:留下心声墨迹,你的评论将是我努力改进的方向!


目录

1. ReplaceingMergeTree建表语句

2. 示例

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

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

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


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

1. 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要消耗大量时间。

2. 示例

2. 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.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]列时,当插入排序字段相同的数据时,保留最新一条数据。



测试指定[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列最大值对应的行。

2.3 测试不同分区中有相同的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 字段不会去重。

👨‍💻如需博文中的资料请私信博主。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/68489.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

unity海康威视原生SDK拉取网络摄像头画面,并展示在一个Material上

原理是使用sdk获取视频流,格式为YUV,然后分离YUV通道到三张不同的Texture2D上,通过shader将三个通道重新输出为原始图像。 我将所用的各个部分已经整理成一个压缩包,免积分下载 压缩包结构如下 使用步骤 1 DLL:放在Plugins文件…

wordpress数据表中标签和分类如何区分?

wordpress中标签和分类是什么关系怎么区分?最后有一个群的网友告诉了我文章ID和标签ID的关系是放在了wp_term_relationships表中,然后我百度了下这个表的结构和相关介绍,发现果然如此,先把文章保存起来: wp_term_rela…

那些年的golang开发经验记录

goland 问题CreateProcess error216, 该版本的 %1 与你运行的 Windows 版本不兼容。请查看计算机的系统信息,然后联系软件发布者 Cannot run program "......" (in directory "D:\project\go\awesomeProject\src\test"): CreateProcess error2…

nginx基于主机和用户访问控制以及缓存简单例子

一.基于主机访问控制 1.修改nginx.conf文件 2.到其他主机上测试 (1)191主机 (2)180主机 二.基于用户访问控制 1.修改nginx.conf文件 2.使用hpasswd为用户创建密码文件,并指定到刚才指定的密码文件webck 3.测试…

Cocos Creator 3.8 后期效果 Shader 编写(2/2) 进阶篇

前言 在上一篇文章中,麒麟子给大家分享了如何在 Cocos Creator 3.8 中的自定义管线中,添加属于自己的后期效果 Shader。 但基于 BlitScreen 的方案,我们只能编写最简单后效 Shader,如果我们想要支持更多复杂的 Shader&#xff0c…

nginx动态同步配置模块nginx-upsync-module

使用场景简介 nginx一般直接在配置文件里配置upstream即可实现负载均衡,但有些特定的环境下此种方式就显得有些局限性。比如后台动态调整节点的时候;调整节点后不想修改配置文件重启nginx。 可以将配置文件从nginx本地迁移到其他第三方服务上如etcd、c…

Claude 2、ChatGPT、Google Bard优劣势比较

​Claude 2: 优势:Claude 2能够一次性处理多达10万个tokens(约7.5万个单词)。 tokens数量反映了模型可以处理的文本长度和上下文数量。tokens越多,模型理解语义的能力就越强)。它在法律、数学和编码等多个…

LinearAlgebraMIT_8_TheRankOfMatrix

这节课中主要讲解根据秩来判断方程组/矩阵的(solvability)解情况,即通过秩来判断(aumented matrix)增广矩阵的解。我们需要直接求解方程组的解就是求解矩阵的解。 x.1 判断(非齐次线性方程组)Axb是否有解 我们以下面这个方程组为例,它具有3个约束条件和…

虹科方案 | 汽车总线协议转换解决方案(二)

上期说到,虹科的PCAN-LIN网关在CAN、LIN总线转换方面有显著的作用,尤其是为BMS电池通信的测试提供了优秀的解决方案。假如您感兴趣,可以点击文末相关链接进行回顾! 而今天,虹科将继续给大家带来Router系列在各个领域的…

AI 绘画Stable Diffusion 研究(六)sd提示词插件

大家好,我是风雨无阻。 今天为大家推荐一款可以有效提升我们使用 Stable Diffusion WebUI 效率的插件, 它就是 prompt-all-in-one, 它不但能直接将 WebUI 中的中文提示词转换为英文,还能一键为关键词加权重,更能建立常…

Redis的AOF持久化

除了RDB持久化功能之外,Redis还提供了AOF持久化功能。与RDB 持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的,如下图所示。 举个例子,如果我们对空白的数据…

vim学习笔记(致敬vim作者)

vim cheat sheet 30. vim 删除大法 vim 删除某个字符之后改行的其他的字符?删除某行之后的其他行?删除某个字符之后的其他字符?【1】删除单个字符? 跳到要删除的字符位置 按下d键然后按下shift 4键 【2】删除某行之后的其他行…

vite+vue3项目环境搭建

1.安装 npm init vite 2.输入项目名称 vue3-project 3.选择框架 说明:vue 4.选择类别 说明:JavaScript 5.进入文件夹 cd vue3-project yarn npm run dev 6.打开local

数据安全加固:深入解析滴滴ES安全认证技术方案

前文分别介绍了滴滴自研的ES强一致性多活是如何实现的、以及如何提升ES的性能潜力。由于ES具有强大的搜索和分析功能,同时也因其开源和易于使用而成为黑客攻击的目标。近些年,业界ES数据泄露事件频发, 以下是一些比较严重的数据泄露案件: 202…

k8s 自身原理 2

前面我们说到 K8S 的基本原理和涉及的四大组件,分享了前两个组件 etcd 和 ApiServer 这一次我们接着分享一波: 调度器 scheduler控制器管理器 controller manager 调度器 scheduler 调度器,见名知意,用于调度 k8s 资源的&…

石子游戏 dfs + 备忘录 JAVA

Alice 和 Bob 用几堆石子在做游戏。一共有偶数堆石子,排成一行;每堆都有 正 整数颗石子,数目为 piles[i] 。 游戏以谁手中的石子最多来决出胜负。石子的 总数 是 奇数 ,所以没有平局。 Alice 和 Bob 轮流进行,Alice 先…

二叉树(4)------收尾

1)最大二叉树 654. 最大二叉树 - 力扣(LeetCode) 题目解析: 1)首先我们找到了整个数组中最大的元素作为我们的根节点,然后再从左区间中找到最大的元素作为当前根节点的左子树,然后再从右区间里面找到最大的元素作为根节点的右子树…

SpringBoot笔记:SpringBoot 集成 Dataway 多数据源配置(二)

文章目录 前言核心代码和配置yml 配置注入多数据源常用Spi实现swagger 配置自定义 Udf指定数据源进行查询 前言 之前简单介绍了一下 Dataway 使用,本文继续介绍一下它的多数据源配置和使用。 核心代码和配置 yml 配置 # springboot多环境配置 #端口,…

企业服务器器中了360后缀勒索病毒怎么解决,勒索病毒解密数据恢复

随着网络威胁的增加,企业服务器成为黑客攻击的目标之一。近期,上海某知名律师事务所的数据库遭到了360后缀的勒索病毒攻击,导致企业服务器内的数据库被360后缀勒索病毒加密。许多重要的数据被锁定无法正常读取,严重影响了企业的正…

【Mybatis】调试查看执行的 SQL 语句

1. 问题场景: 记录日常开发过程中 Mybatis 调试 SQL 语句,想要查看Mybatis 中执行的 SQL语句,导致定位问题困难 2. 解决方式 双击shift找到mybatis源码中的 MappedStatement的getBoundSql()方法 public BoundSql getBoundSql(Object para…