Clickhouse作为一个OLAP数据库,它对事务的支持非常有限。Clickhouse提供了MUTATION操作(通过ALTER TABLE语句)来实现数据的更新、删除,但这是一种“较重”的操作,它与标准SQL语法中的UPDATE、DELETE不同,是异步执行的,对于批量数据不频繁的更新或删除比较有用 。除了MUTATION操作,Clickhouse还可以通过CollapsingMergeTree、VersionedCollapsingMergeTree、ReplacingMergeTree结合具体业务数据结构来实现数据的更新、删除,这三种方式都通过INSERT语句插入最新的数据,新数据会“抵消”或“替换”掉老数据,但是“抵消”或“替换”都是发生在数据文件后台Merge时,也就是说,在Merge之前,新数据和老数据会同时存在。因此,我们需要在查询时做一些处理,避免查询到老数据。Clickhouse官方文档提供了使用CollapsingMergeTree、VersionedCollapsingMergeTree的指导 。相比于CollapsingMergeTree、VersionedCollapsingMergeTree需要标记位字段、版本字段,用ReplacingMergeTree来实现数据的更新删除会更加方便,这里着重介绍一下如何用ReplacingMergeTree来实现数据的更新删除。

我们假设一个需要频繁数据更新的场景,如某市用户用电量的统计,我们知道,用户的用电量每分每秒都有可能发生变化,所以会涉及到数据频繁的更新。首先,创建一张表来记录某市所有用户的用电量。

CREATE TABLE IF NOT EXISTS default.PowerConsumption_local ON CLUSTER default_cluster
(User_ID             UInt64                              COMMENT '用户ID',Record_Time         DateTime    DEFAULT toDateTime(0)   COMMENT '电量记录时间',District_Code       UInt8                               COMMENT '用户所在行政区编码',Address             String                              COMMENT '用户地址',Power               UInt64                              COMMENT '用电量',Deleted             BOOLEAN     DEFAULT 0               COMMENT '数据是否被删除'
)
ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/default.PowerConsumption_local/{shard}', '{replica}', Record_Time)
ORDER BY (User_ID, Address)
PARTITION BY District_Code;
CREATE TABLE default.PowerConsumption ON CLUSTER default_cluster AS default.PowerConsumption_local
ENGINE = Distributed(default_cluster, default, PowerConsumption_local, rand());

PowerConsumption_local为本地表,PowerConsumption为对应的分布式表。其中PowerConsumption_local使用ReplicatedReplacingMergeTree表引擎,第三个参数‘Record_Time’表示相同主键的多条数据,只会保留Record_Time最大的一条,我们正是利用ReplacingMergeTree的这一特性来实现数据的更新删除。因此,在选择主键时,我们需要确保主键唯一。这里我们选择(User_ID, Address)来作为主键,因为用户ID加上用户的地址可以确定唯一的一个电表,不会出现第二个相同的电表,所以对于某个电表多条数据,只会保留电量记录时间最新的一条。

然后我们向表中插入10条数据:

INSERT INTO default.PowerConsumption VALUES (0, '2021-10-30 12:00:00', 3, 'Yanta', rand64() % 1000 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (1, '2021-10-30 12:10:00', 2, 'Beilin', rand64() % 1000 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (2, '2021-10-30 12:15:00', 1, 'Weiyang', rand64() % 1000 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (3, '2021-10-30 12:18:00', 1, 'Gaoxin', rand64() % 1000 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (4, '2021-10-30 12:23:00', 2, 'Qujiang', rand64() % 1000 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (5, '2021-10-30 12:43:00', 3, 'Baqiao', rand64() % 1000 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (6, '2021-10-30 12:45:00', 1, 'Lianhu', rand64() % 1000 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (7, '2021-10-30 12:46:00', 3, 'Changan', rand64() % 1000 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (8, '2021-10-30 12:55:00', 1, 'Qianhan', rand64() % 1000 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (9, '2021-10-30 12:57:00', 4, 'Fengdong', rand64() % 1000 + 1, 0);

表中数据如图所示:

假如现在我们要行政区编码为1的所有用户数据都需要更新,我们插入最新的数据:

INSERT INTO default.PowerConsumption VALUES (2, now(), 1, 'Weiyang', rand64() % 100 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (3, now(), 1, 'Gaoxin', rand64() % 100 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (6, now(), 1, 'Lianhu', rand64() % 100 + 1, 0);
INSERT INTO default.PowerConsumption VALUES (8, now(), 1, 'Qianhan', rand64() % 100 + 1, 0);

插入最新数据后,表中数据如图所示:

可以看到,此时新插入的数据与老数据同时存在于表中,因为后台数据文件还没有进行Merge,“替换”还没有发生,这时就需要对查询语句做一些处理来过滤掉老数据,函数argMax(a, b)可以按照b的最大值取a的值,所以通过如下查询语句就可以只获取到最新数据:

SELECTUser_ID,max(Record_Time) AS R_Time,District_Code,Address,argMax(Power, Record_Time) AS Power,argMax(Deleted, Record_Time) AS Deleted
FROM default.PowerConsumption
GROUP BYUser_ID,Address,District_Code
HAVING Deleted = 0;

查询结果如下图:

为了更方便我们查询,这里可以创建一个视图:

CREATE VIEW PowerConsumption_view ON CLUSTER default_cluster AS
SELECTUser_ID,max(Record_Time) AS R_Time,District_Code,Address,argMax(Power, Record_Time) AS Power,argMax(Deleted, Record_Time) AS Deleted
FROM default.PowerConsumption
GROUP BYUser_ID,Address,District_Code
HAVING Deleted = 0;

通过该视图,可以查询到最新的数据:

假如现在我们又需要删除用户ID为0的数据,我们需要插入一条User_ID字段为0,Deleted字段为1的数据:

INSERT INTO default.PowerConsumption VALUES (0, now(), 3, 'Yanta', null, 1);

查询视图,发现User_ID为0的数据已经查询不到了:

通过如上方法,我们可以实现Clickhouse数据的更新、删除,就好像在使用OLTP数据库一样,但我们应该清楚,实际上老数据真正的删除是在数据文件Merge时发生的,只有在Merge后,老数据才会真正物理意义上的删除掉。

本文由华为云发布。

Clickhouse如何实现数据更新相关推荐

  1. ReplacingMergeTree:实现Clickhouse数据更新

    摘要:Clickhouse作为一个OLAP数据库,它对事务的支持非常有限.本文主要介绍通过ReplacingMergeTree来实现Clickhouse数据的更新.删除. 本文分享自华为云社区< ...

  2. clickhouse hadoop_大数据分析之解决Hadoop的短板,实时大数据分析引擎ClickHouse解析...

    本篇文章探讨了大数据分析之解决Hadoop的短板,实时大数据分析引擎ClickHouse解析,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入. 一.背景 提到大数据不得不提Hado ...

  3. ClickHouse vs StarRocks 全场景MPP数据库选型对比

    ClickHouse vs StarRocks 选型对比 面向列存的 DBMS 新的选择 Hadoop 从诞生已经十三年了,Hadoop 的供应商争先恐后的为 Hadoop 贡献各种开源插件,发明各种 ...

  4. clickhouse集群表删除_携程用ClickHouse轻松玩转每天十亿级数据更新

    作者介绍 蔡岳毅,携程酒店大数据高级研发经理,负责酒店数据智能平台研发,大数据技术创新工作.喜欢探索研究大数据的开源技术框架. 一.背景 携程酒店每天有上千表,累计十多亿数据更新,如何保证数据更新过程 ...

  5. clickhouse 增量更新_干货 | 每天十亿级数据更新,秒出查询结果,ClickHouse在携程酒店的应用...

    本文转自| 携程技术中心  作者 | 蔡岳毅 作者简介蔡岳毅,携程酒店大数据高级研发经理,负责酒店数据智能平台研发,大数据技术创新工作.喜欢探索研究大数据的开源技术框架.一.背景 1)携程酒店每天有上 ...

  6. ClickHouse数据分析列式数据库概述

    一. 概述 随着物联网IOT时代的来临,IOT设备感知和报警存储的数据越来越大,有用的价值数据需要数据分析师去分析.大数据分析成了非常重要的环节.当然近两年开启的开源大潮,为大数据分析工程师提供了十分 ...

  7. ClickHouse:人群圈选业务的大杀器

    简介:随着数据时代的发展,各行各业数据平台的体量越来越大,用户个性化运营的诉求也越来越突出,用户标签系统,做为个性化千人千面运营的基础服务,应运而生.如今,几乎所有行业(如互联网.游戏.教育等)都有实 ...

  8. ClickHouse 在广告系统场景中的实践

    目录 前言 需求分析 主要特点 适用场景 I/O情况 测试结论 前言 随着数据量的增长,传统DB已经无法满足实时聚合分组排序分析需求,目前比较流行日OLAP系统有:Presto,Druid,Kylin ...

  9. ClickHouse 详细集群部署方案

    基本介绍: ClickHouse 来自俄罗斯最大的搜索公司Yandex,配置文件中可以看到Yandex的样子,于2016年开源. ClickHouse是面向OLAP的分布式列式DBMS,OLAP(在线 ...

最新文章

  1. poj1523(割点)
  2. 数字转化成时分秒(二)
  3. JAVA实现N皇后问题(回溯法)
  4. c语言中listnode是什么意思,怎么理解typedef Node * List
  5. C#LeetCode刷题-队列
  6. Mac homebrew报错Error: homebrew-core is a shallow clone.
  7. php 封装的调试方法,关于php面向的特性之封装
  8. 二维正则表达式v0.1
  9. @开发者 争抢技术红利,百度自研 4 款人脸硬件要和大家见面了!
  10. ajax获取nodejs的值,jquery - NodeJS如何获取服务器中的数据,通过POST从jquery ajax调用发送 - 堆栈内存溢出...
  11. 地图不显示_图灵搜不显示地图,软件打开一片空白,怎么解决?
  12. 菜鸟译文(二)——使用Java泛型构造模板方法模式
  13. 2021爱分析・区域性银行数字化厂商全景报告
  14. 手机远程控制电脑方法(TeamViewer vs 向日葵)
  15. 百度地图API的IP定位城市和浏览器定位
  16. NAXX Demo3_JSQ_02 BUG
  17. openstack跟着官网部署过程
  18. JZOJ2018.07.12【2018提高组】模拟B组 魔道研究
  19. min capacitance 违例
  20. 关于数学计算机手抄报简单的,简单漂亮的数学手抄报图片大全

热门文章

  1. Linux 挂载4T硬盘到根目录
  2. 4t硬盘实际容量是多少_怎么对大容量硬盘(例如4T硬盘)进行查看并分区
  3. vue-router 判断是否登陆,未登录跳转登陆页面
  4. .NET DataGridView 单元格添加日历选择控件
  5. python格式化字符_Python格式化字符串
  6. 信号数据shannon entropy计算
  7. UVA 11021 麻球繁衍
  8. C 程序设计语言——第四章练习题
  9. 学海无涯!java流式计算性能
  10. 宣布全面开源,微众银行正下一盘区块链商业的大棋