ClickHouse实战–使用ReplacingMergeTree来更新数据

概述

通过ReplacingMergeTree引擎的表可以更新主键相同和版本相同的数据行。本文介绍ReplacingMergeTree引擎的使用方式和数据更新的操作。

ReplacingMergeTree实战

创建本地表

创建一张本地表:stu_local

CREATE TABLE if not exists test_db.stu_local on cluster perftest_2shards_1replicas
(`id` Int64,`stu_code` Int32,`stu_name` String,`total_cnt` Int64,`event_time` DateTime,`version`  DateTime
)
Engine=ReplacingMergeTree(version)
PARTITION BY toYYYYMMDD(event_time)
ORDER BY id;

注意:on cluster后面的是集群名,这个根据system.clusters表中的名称进行修改。

创建分布式表

CREATE TABLE if not exists test_db.stu_all on cluster perftest_2shards_1replicas
as test_db.stu_local
ENGINE = Distributed(perftest_2shards_1replicas, test_db, stu_local, intHash64(id));

注意:为了让相同id的数据行分布到同一个节点上,就不能再使用rand()这个sharding策略。而是需要通过一个hash函数来让相同主键的数据分片到相同的节点上。

由于,我们的主键是:id。所以,可以使用一个hash函数来做这个分片策略。hash函数的说明可以参考官方文档:Hash Functions。

向分布式表插入数据

insert into test_db.stu_all (id, stu_code, stu_name, total_cnt, event_time,version) values (1, 4000, 'guangzhou', 420000, toDateTime(now()), toDateTime(now()));
insert into test_db.stu_all (id, stu_code, stu_name, total_cnt, event_time,version) values (2, 5000, 'shenzhan', 55000, toDateTime(now()), toDateTime(now()));
insert into test_db.stu_all (id, stu_code, stu_name, total_cnt, event_time,version) values (3, 6000, 'huizhou', 65000, toDateTime(now()), toDateTime(now()));
insert into test_db.stu_all (id, stu_code, stu_name, total_cnt, event_time,version) values (4, 7000, 'huizhou', 75000, toDateTime(now()), toDateTime(now()));
insert into test_db.stu_all (id, stu_code, stu_name, total_cnt, event_time,version) values (5, 8000, 'huizhou', 75001, toDateTime(now()), toDateTime(now()));

再插入两条相同的id为1和2的数据,此时version的值会获取当前的时间,所以和以前的数据不同。

insert into test_db.stu_all (id, stu_code, stu_name, total_cnt, event_time,version) values (1, 4000, 'guangzhou', 420000, toDateTime(now()), toDateTime(now()));
insert into test_db.stu_all (id, stu_code, stu_name, total_cnt, event_time,version) values (2, 5000, 'shenzhan', 55000, toDateTime(now()), toDateTime(now()));

此时可以看到,表中的数据如下:

id   stu_code    stu_name    total_cnt   event_time  version
2   5000    shenzhan    55000   2022-05-03 16:44:19.000 2022-05-03 16:44:19.000
2   5000    shenzhan    55000   2022-05-03 16:50:01.000 2022-05-03 16:50:01.000
1   4000    guangzhou   420000  2022-05-03 16:50:01.000 2022-05-03 16:50:01.000
1   4000    guangzhou   420000  2022-05-03 16:45:53.000 2022-05-03 16:45:53.000
3   6000    huizhou 65000   2022-05-03 16:48:19.000 2022-05-03 16:48:19.000
4   7000    huizhou 75000   2022-05-03 16:48:28.000 2022-05-03 16:48:28.000
5   8000    huizhou 75001   2022-05-03 16:48:34.000 2022-05-03 16:48:34.000

添加一个final字段后的结果如下:

SELECT * from test_db.stu_all sa final;

该sql的执行结果如下:

id   stu_code    stu_name    total_cnt   event_time  version
2   5000    shenzhan    55000   2022-05-03 16:50:01.000 2022-05-03 16:50:01.000
1   4000    guangzhou   420000  2022-05-03 16:50:01.000 2022-05-03 16:50:01.000
4   7000    huizhou 75000   2022-05-03 16:48:28.000 2022-05-03 16:48:28.000
5   8000    huizhou 75001   2022-05-03 16:48:34.000 2022-05-03 16:48:34.000
3   6000    huizhou 65000   2022-05-03 16:48:19.000 2022-05-03 16:48:19.000
OPTIMIZE语句

可以使用OPTIMIZE语句来让数据合并立刻生效。但该语句会引发大量的读写,所以,需要谨慎使用。

OPTIMIZE table test_db.stu_local on cluster perftest_2shards_1replicas;

再次执行查询sql,可以看到数据已经被合并了。

以上例子的问题

注意以上例子可能达不到预期的效果,本来我们希望相同id的数据合并(只保留一条),但以上建表方式可能达不到效果。为什么呢?

其实,原因是由于我们的分区字段创建的有问题。我们说过,只有相同分区的数据才会合并,我们使用的是toYYYYMMDD(event_time)–按天的日期作为分区,这意味着,同一天的相同的id数据行会在同一个分区,会被合并。而不同日期的数据是不会被合并的。

插入两条不同日期的数据:

insert into test_db.stu_all (id, stu_code, stu_name, total_cnt, event_time,version) values (1, 4000, 'guangzhou', 420000, toDateTime('2022-02-21 00:00:00'), toDateTime(now()));insert into test_db.stu_all (id, stu_code, stu_name, total_cnt, event_time,version) values (2, 5000, 'shenzhan', 55000, toDateTime('2022-02-21 00:00:00'), toDateTime(now()));

执行optimize语句:

OPTIMIZE table test_db.stu_local on cluster perftest_2shards_1replicas;

再查询一下数据:

id   stu_code    stu_name    total_cnt   event_time  version1    4000    guangzhou   420000  2022-05-03 16:50:01.000 2022-05-03 16:50:01.0001    4000    guangzhou   420000  2022-02-21 00:00:00.000 2022-05-03 17:07:22.0002    5000    shenzhan    55000   2022-05-03 16:50:01.000 2022-05-03 16:50:01.0002    5000    shenzhan    55000   2022-02-21 00:00:00.000 2022-05-03 17:07:26.0003    6000    huizhou 65000   2022-05-03 16:48:19.000 2022-05-03 16:48:19.0004    7000    huizhou 75000   2022-05-03 16:48:28.000 2022-05-03 16:48:28.0005    8000    huizhou 75001   2022-05-03 16:48:34.000 2022-05-03 16:48:34.000

这说明了Clickhouse没有相同id且分区不同的数据行。

所以,要想实现数据合并,需要让相同id的数据落到相同分区中。比如对于用户信息,可以添加一个部门等字段,那这个字段作为分区,这样就可以让相同用户id的数据落到相同分区了。

但注意,虽然后台并没有实现数据合并,但当我们添加final时,查询的结果却是正确的:

SELECT * from test_db.stu_all sa final order by id;

通过添加final能得到正确的结果。

id   stu_code    stu_name    total_cnt   event_time  version1    4000    guangzhou   420000  2022-02-21 00:00:00.000 2022-05-03 17:07:22.0002    5000    shenzhan    55000   2022-02-21 00:00:00.000 2022-05-03 17:07:26.0003    6000    huizhou 65000   2022-05-03 16:48:19.000 2022-05-03 16:48:19.0004    7000    huizhou 75000   2022-05-03 16:48:28.000 2022-05-03 16:48:28.0005    8000    huizhou 75001   2022-05-03 16:48:34.000 2022-05-03 16:48:34.000

但由于数据并没有真正合并,所以添加final查询时,随着垃圾数据越来越多,会严重影响性能。所以,还是需要想办法把该删除的数据合并掉。

小结

本文通过一些例子介绍了如何使用ReplacingMergeTree引擎。在使用ReplacingMergeTree要注意:(1)只有相同分区的数据行才会被合并,所以,必须要注意让需要合并的数据落到相同分区中。(2)若是分布式表,还需要注意要让需要合并的数据落到相同的节点上。(3)不能频繁使用optimize操作;(4)ReplacingMergeTree有一定的适用场景,不是所有的场景,需要根据业务需要进行选择。

ClickHouse实战--使用ReplacingMergeTree来更新数据相关推荐

  1. 图文详解 DBMS 数据库管理系统三层架构体系(三级模式)《ClickHouse 实战:企业级大数据分析引擎》...

    引文 计算机科学领域的所有问题,都可以通过添加一层中间层来解决.通过在用户和计算机中间添加一层逻辑层(概念模型层),于是就有了"数据库的三级模式":数据库在三个级别 (层次)上进行 ...

  2. 《ClickHouse 实战:企业级大数据分析》

    计算机科学领域的所有问题,都可以通过添加一层中间层来解决.通过在用户和计算机中间添加一层逻辑层(概念模型层),于是就有了"数据库的三级模式":数据库在三个级别 (层次)上进行 抽象 ...

  3. DBMS 数据库管理系统的三级模式架构《ClickHouse 实战:企业级大数据分析引擎》...

    引文 计算机科学领域的所有问题,都可以通过添加一层中间层来解决.通过在用户和计算机中间添加一层逻辑层(概念模型层),于是就有了"数据库的三级模式":数据库在三个级别 (层次)上进行 ...

  4. 一招教你数据仓库如何高效批量导入与更新数据

    摘要:GaussDB(DWS)支持的MERGE INTO功能,可以同时进行大数据量的更新与插入.对于数据仓库是一项非常重要的技术. 本文分享自华为云社区<一招教你如何高效批量导入与更新数据> ...

  5. [转载]Qt之模型/视图(实时更新数据)

    原文地址:Qt之模型/视图(实时更新数据)作者:一去丶二三里 上两节简单介绍了Qt中对于模型/视图的编程,大部分助手里说的很清楚了,现在就开始实战部分吧! 在实际应用中,视图展示的数据往往并非一成不变 ...

  6. [转载]Qt之模型/视图(实时更新数据)_vortex_新浪博客

    原文地址:Qt之模型/视图(实时更新数据)作者:一去丶二三里 上两节简单介绍了Qt中对于模型/视图的编程,大部分助手里说的很清楚了,现在就开始实战部分吧! 在实际应用中,视图展示的数据往往并非一成不变 ...

  7. Redis入门到实战(实战篇)缓存更新、穿透、雪崩、击穿!

    Redis基础篇 Java面试宝典-redis 实战篇Redis 开篇导读 亲爱的小伙伴们大家好,马上咱们就开始实战篇的内容了,相信通过本章的学习,小伙伴们就能理解各种redis的使用啦,接下来咱们来 ...

  8. 网页爬虫实战:全国电动汽车充电站数据

    爬虫实战:全国电动汽车充电站数据 项目详情页请访问 Github,喜欢的话就去加个 star 吧 ,附上Github个人博客 先放张效果图,吸引一下眼球 下面进入正题~ 想必大家某些时候总需要爬取一些 ...

  9. ChatGPT全栈开发实战:从需求分析到数据可视化,一站式指南助你快速构建全面应用

    <ChatGPT全栈开发实战:从需求分析到数据可视化,一站式指南助你快速构建全面应用>是一本旨在引领我们进入全栈开发世界的综合指南.通过结合强大的ChatGPT技术和全栈开发的实践,我们将 ...

最新文章

  1. 【组队学习】【32期】动手学数据分析
  2. spring MVC - Inteceptors(拦截器)
  3. python 回文数
  4. 青瓷引擎之纯JavaScript打造HTML5游戏第二弹——《跳跃的方块》Part 3
  5. linux limit
  6. 修改Windows登陆时显示上一次登陆的用户名
  7. poj 1961 Period kmp基础
  8. WinRAR 曝出代码执行漏洞,你的官方中文无广告版该升级了
  9. 读取excel数据批量填充world
  10. v3.exo是什么文件_exo是什么文件?
  11. 吞下西甲英超中超成体育大胃王,PPTV还有哪些大招?
  12. 自动化测试框架之unittest
  13. CC2530 CC2530F256RHAR 一款ZigBee SOC芯片
  14. 软件测试必备基础知识
  15. C++ int类型最大最小数字(16进制)
  16. python图像数据是几维数据_Numpy高维数据的理解
  17. 微信公众平台按钮及菜单创建
  18. 纳米的尺度究竟有多大?
  19. 年味儿一年不如一年图鉴
  20. [noi-2291]快速幂运算

热门文章

  1. 阻抗跟踪电量计开发及量产流程
  2. ROS MarkerArray的几种常见用法
  3. java 下载图片并打压缩包
  4. Java jbcl.jar下载
  5. bzoj3786星系探索(splay维护dfs序)
  6. 用cdn网址的方式引入echart和echart-gl
  7. fmri与GLM应用
  8. 结构光-----激光散斑图像评测算法
  9. 公司、分公司、子公司、有限公司、企业、个体户的区别!
  10. JVM第二天-ClassFileFormat