客快物流大数据项目(九十五):ClickHouse的CollapsingMergeTree深入了解

举报
Lansonli 发表于 2022/12/28 17:26:18 2022/12/28
【摘要】 ​ClickHouse的CollapsingMergeTree深入了解在ClickHouse中不支持对数据update和delete操作(不能使用标准的更新和删除语法操作CK),但在增量计算场景下,状态更新是一个常见的现象,此时update操作似乎更符合这种需求。ClickHouse提供了一个CollapsingMergeTree表引擎,它继承于MergeTree引擎,是通过一种变通的方式来...

ClickHouse的CollapsingMergeTree深入了解

ClickHouse中不支持对数据update和delete操作(不能使用标准的更新和删除语法操作CK),但在增量计算场景下,状态更新是一个常见的现象,此时update操作似乎更符合这种需求。

ClickHouse提供了一个CollapsingMergeTree表引擎,它继承于MergeTree引擎,是通过一种变通的方式来实现状态的更新

CollapsingMergeTree表引擎需要的建表语句与MergeTree引擎基本一致,惟一的区别是需要指定Sign列(必须是Int8类型)。这个Sign列有1和-1两个值,1表示为状态行,当需要新增一个状态时,需要将insert语句中的Sign列值设为1;-1表示为取消行,当需要删除一个状态时,需要将insert语句中的Sign列值设为-1

这其实是插入了两行除Sign列值不同,但其他列值均相同的数据。因为有了Sign列的存在,当触发后台合并时,会找到存在状态行与取消行对应的数据,然后进行折叠操作,也就是同时删除了这两行数据

状态行与取消行不折叠有两种情况。

  • 第一种是合并机制,由于合并在后台发生,且具体的执行时机不可预测,所以可能会存在状态行与取消行还没有被折叠的情况,这时会出现数据冗余;
  • 第二种是当乱序插入时(CollapsingMergeTree仅允许严格连续插入),ClickHouse不能保证相同主键的行数据落在同一个节点上,但不同节点上的数据是无法折叠的。为了得到正确的查询结果,需要将count(col)、sum(col)改写成sum (Sign)、sum(col * Sign)。

如果在业务系统中使用ClickHouse的CollapsingMergeTree引擎表,当状态行已经存在,要插入取消行来删除数据的时候,必须存储一份状态行数据来执行insert语句删除。这种情况下,就有些麻烦,因为同一个业务数据的状态需要我们记录上一次原始态数据,和当前最新态的数据,才能完成原始态数据删除,最新态数据存储到ClickHouse中。

一、创建CollapsingMergeTree引擎表的语法

语法结构

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
        name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
        name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
        ...
) ENGINE = CollapsingMergeTree(sign)
[PARTITION BY expr]
[ORDER BY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]


CollapsingMergeTree(sign)参数说明

Sign是列名称,必须是Int8类型,用来标志Sign列。Sign列值为1是状态行,为-1是取消行。

二、创建CollapsingMergeTree引擎的表

create table tbl_test_collapsingmergetree_day_mall_sale (
        mallId UInt64,
        mallName String,
        totalAmount Decimal(32,2),
        cdt Date,
        sign Int8
) engine=CollapsingMergeTree(sign) partition by toYYYYMMDD(cdt) order by mallId;


三、插入数据到CollapsingMergeTree引擎的表

第一次插入2条sign=1的数据

注意:当一行数据的sign列=1时,是标记该行数据属于状态行。也就是说,我们插入了两条状态行数据。

insert into tbl_test_collapsingmergetree_day_mall_sale(mallId,mallName,totalAmount,cdt,sign) values(1,'西单大悦城',17649135.64,'2019-12-24',1);
insert into tbl_test_collapsingmergetree_day_mall_sale(mallId,mallName,totalAmount,cdt,sign) values(2,'朝阳大悦城',16341742.99,'2019-12-24',1);

查询第一次插入的数据

select * from tbl_test_collapsingmergetree_day_mall_sale;

第二次插入2条sign=-1的数据

注意:当一行数据的sign列=-1时,是标记该行数据属于取消行(取消行有一个要求:除了sign字段值不同,其他字段值必须是相同的。这样一来,就有点麻烦,因为我们在状态发生变化时,还需要保存着未发生状态变化的数据。这个场景类似于修改数据,但由于ClickHouse本身的特性不支持update,所以其提供了一种变通的方式,即通过CollapsingMergeTree引擎来支持这个场景)。取消行指的是当这一行数据有了新的状态变化,需要先取消原来存储的数据,使ClickHouse合并时来删除这些sign由1变成-1的数据,虽然合并发生时机不确定,但如果触发了合并操作就一定会被删除。这样一来,我们将有新状态变化的数据再次插入到表,就仍然是2条数据。

insert into tbl_test_collapsingmergetree_day_mall_sale(mallId,mallName,totalAmount,cdt,sign) values(1,'西单大悦城',17649135.64,'2019-12-24',-1);
insert into tbl_test_collapsingmergetree_day_mall_sale(mallId,mallName,totalAmount,cdt,sign) values(2,'朝阳大悦城',16341742.99,'2019-12-24',-1);

对表执行强制合并

optimize table tbl_test_collapsingmergetree_day_mall_sale final;

然后发现查询数据时,表中已经没有了数据。这表示当触发合并操作时,会合并状态行与取消行同时存在的数据。

第三次插入3条数据

insert into tbl_test_collapsingmergetree_day_mall_sale(mallId,mallName,totalAmount,cdt,sign) values(1,'西单大悦城',17649135.64,'2019-12-24',1);
insert into tbl_test_collapsingmergetree_day_mall_sale(mallId,mallName,totalAmount,cdt,sign) values(2,'朝阳大悦城',16341742.99,'2019-12-24',1);
insert into tbl_test_collapsingmergetree_day_mall_sale(mallId,mallName,totalAmount,cdt,sign) values(1,'西单大悦城',17649135.64,'2019-12-24',-1);
select * from tbl_test_collapsingmergetree_day_mall_sale;
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。