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

news2024/11/24 9:53:03

 进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注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.coloradmin.cn/o/845527.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Session与Cookie的区别(五)

储存状态的方式 小明的故事说完了,该来把上面这一段变成网络的实际案例了。其实在网络世界中问题也是一样的。 前面已经提到过我们会把状态存在 Cookie 里面,让 Request 之间能够变得有关联。 假设我们今天要来做一个会员系统,那我要怎么知道…

24届近5年南京航空航天大学自动化考研院校分析

今天给大家带来的是南京航空航天大学控制考研分析 满满干货~还不快快点赞收藏 一、南京航空航天大学 学校简介 南京航空航天大学创建于1952年10月,是新中国自己创办的第一批航空高等院校之一。1978年被国务院确定为全国重点大学;1981年经…

Llama 2 云端部署与API调用【AWS SageMaker】

Meta 刚刚发布了 Llama 2 大模型。如果你和我们一样,你一定会迫不及待地想要亲自动手并用它来构建。 推荐:用 NSDT设计器 快速搭建可编程3D场景。 使用任何类型的 LLM 进行构建的第一步是将其托管在某处并通过 API 使用它。 然后你的开发人员可以轻松地将…

Java技术整理(4)—— 多线程并发篇

1、Java 线程实现/创建方式 (1)继承Thread类 Thread类本质上是实现了Runnable接口的实例,代表一个线程的实例,通过start()启动,自动执行run()方法。 (2)实现Runnable接口 Runnable是一个没有…

2023 java web面试秘籍

目录 第一章:Java Web基础知识1.介绍3.Java Web基本概念 4.常见面试问题第二章:Java Web核心概念和技术1.介绍3.Servlet和JSP4.Web安全5.常见面试问题 第三章:Java Web高级概念和技术1.介绍3.Spring框架4.安全性5.常见面试问题 第四章&#x…

Clickhouse 数据存储

一、数据分区 数据是以分区目录的形式组织的,每个分区独立分开存储.这种形式,查询数据时,可以有效的跳过无用的数据文件。 1.1 数据分区的规则 分区键的取值,生成分区ID,分区根据ID决定。根据分区键的数据类型不同&am…

springboot房地产管理java购房租房二手房j客户sp源代码mysql

本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 springboot房地产管理 系统1权限:管理员 …

Spring Boot多级缓存实现方案

1.背景 缓存,就是让数据更接近使用者,让访问速度加快,从而提升系统性能。工作机制大概是先从缓存中加载数据,如果没有,再从慢速设备(eg:数据库)中加载数据并同步到缓存中。 所谓多级缓存,是指在整个系统架…

2、简单上手+el挂载点+v-xx(v-text、v-html、v-on、v-show、v-if、v-bind、v-for)

官网&#xff1a; vue3&#xff1a;https://cn.vuejs.org/ vue2&#xff1a;https://v2.cn.vuejs.org/v2/guide/ 简单上手&#xff1a; 流程&#xff1a; 导入开发版本的Vue.js <!--开发环境版本&#xff0c;包含了有帮助的命令行警告--> <script src"https…

【IDEA+Spark Streaming 3.4.1+Dstream监控套接字流统计WordCount保存至MySQL8】

【IDEASpark Streaming 3.4.1Dstream监控套接字流统计WordCount保存至MySQL8】 把DStream写入到MySQL数据库中 Spark 3.4.1MySQL 8.0.30sbt 1.9.2 文章目录 【IDEASpark Streaming 3.4.1Dstream监控套接字流统计WordCount保存至MySQL8】前言一、背景说明二、使用步骤1.引入库2…

一个月 PMP 3A上岸经验复盘

2023年5月参加的线下考试&#xff0c;总复习时间一个月左右&#xff0c;刷到3A小绿饼 作为拖延症晚期&#xff0b;工作任务比较多&#xff0c;所以全程没有跟上老师的复习&#xff0c;最后集中在考前一个月临时抱佛脚&#xff0c;成功上岸不是梦 下面分享一下报名和备考经验 1月…

python画小车

文章目录 import matplotlib.pyplot as plt from matplotlib.patches import Rectangle import matplotlib.transforms as transforms import numpy as np # 创建图形窗口和坐标轴对象 fig, ax = plt.subplots()# 绘制小车矩形 def plot_robot(x, y, yaw, robot_length=2, robo…

python编写ocr识别图片汉字

当你需要构建一个简单的图形用户界面&#xff08;GUI&#xff09;应用程序&#xff0c;并在其中实现光学字符识别&#xff08;OCR&#xff09;功能时&#xff0c;wxPython是一个强大而灵活的选择。wxPython是一个基于Python的跨平台GUI开发框架&#xff0c;结合了wxWidgets C库…

Spring MVC项目概述及创建

Spring MVC项目概述及创建 1.什么是Spring MVC Spring MVC是基于SevletAPI的原始Web框架。Spring MVC项目也叫做SpringWeb项目。 它是在springboot项目中引入了web框架&#xff0c;原本的spring项目不具备网络通信能力&#xff0c;而spring mvc允许http响应&#xff0c;当用…

芯片热处理设备 HTR-4立式4寸快速退火炉

HTR-4立式4寸快速退火炉 HTR-4立式4寸快速退火炉&#xff08;芯片热处理设备&#xff09;广泛应用在IC晶圆、LED晶圆、MEMS、化合物半导体和功率器件等多种芯片产品的生产&#xff0c;和欧姆接触快速合金、离子注入退火、氧化物生长、消除应力和致密化等工艺当中&#xff0c;通…

调整vscode

调整vscode 连wifi linux连接wifi

noisy_crt 题目复现

文章目录 题一([NeepuCtf 2023]loud)题目描述&#xff1a;题目分析&#xff1a; 题二([NeepuCtf 2023]loud2)题目描述&#xff1a;题目分析&#xff1a; 浅记一下 论文在此 不过吧&#xff0c;内容太多了&#xff0c;我也不想看 题一([NeepuCtf 2023]loud) 题目描述&#xff…

C语言调试实用技巧之 2

导言&#xff1a; 今天也给大家介绍一些调试技巧 1.如何写出好&#xff08;易于调试&#xff09;的代码 1.1标准&#xff1a; 1.2推荐技巧 1.2.1assert&#xff08;&#xff09;//断言 用assert代替if语句 提示&#xff1a;assert是宏&#xff0c;不是函数 需要包含的头文…

配置Picgo图床之COS、OSS、Github图床

简介 PicGo是一款开源的图片上传和管理工具&#xff0c;它提供了简单易用的界面和丰富的功能&#xff0c;方便用户上传、管理和分享图片。 以下是PicGo的一些主要特点和功能&#xff1a; 图片上传&#xff1a;PicGo支持将本地图片快速上传到云存储服务&#xff0c;如七牛云、…

NamedParameterJdbcTemplate.queryForList 方法的使用说明

objectMapper.configure 方法是 Jackson 提供的一个用于配置 ObjectMapper 对象的方法。ObjectMapper 是 Jackson 库的核心类&#xff0c;用于将 Java 对象与 JSON 数据相互转换。 configure 方法的作用是设置 ObjectMapper 的配置选项&#xff0c;例如设置日期格式、设置序列…