关于Clickhouse的CollapsingMergeTree引擎生产环境踩坑分享

前言

在之前的文章中,已经跟铁子们分享了关于Clickhouse数据库CollapsingMergeTree表引擎的相关应用。最近在处理生产环境业务历史数据的过程中,发现还有一些容易踩坑的点在上次文章中没有记录,这里给铁子们再补充一下吧,如果后续你们有相同的业务需求,应该是比较有价值的干货。

引擎解释

clickhouse官方文档地址点击这里

在这里,我们结合官方文档可以看到,他是一个折叠引擎,是什么意思呢,就是说如果两条数据的所有字段,除了sidn字段是1和-1,那这两条数据在合并的过程中就会相互抵消,相当于删除操作。

为什么使用CollapsingMergeTree引擎

clickhouse中的删除和更新是异步的,那这样就有一个致命的问题,比如咱们的需求是先删除旧数据,再插入新数据,由于他是异步的,有可能在你插入之后,他才开始执行删除操作,就会导致数据丢失的情况。这个是我在生产环境做聚合报表的过程中发现的,大伙可以稍微留意一下,对于任何生产的数据都要持谨慎态度。

实战讲解

创建表

CREATE TABLE IF NOT EXISTS test_table
(
    `pmp_id` Int64 COMMENT '项目ID',
    `city` Int64 COMMENT '',
    `statistic_date` DateTime COMMENT '统计日期',
    `stu_num` Int64 DEFAULT 0 COMMENT '学生人数',
    `class_room_num ` Int64 DEFAULT 0 COMMENT '教室数量',
    `sign` Int8 COMMENT '标志位'
)
ENGINE = CollapsingMergeTree(sign)
PARTITION BY toYYYYMM(statistic_date)
PRIMARY KEY (pmp_id, city, statistic_date)
ORDER BY (pmp_id, city, statistic_date)
SETTINGS index_granularity = 8192;

我们这里创建一张测试表,注意sign字段是标志位字段

插入一条数据

insert into  test_table(pmp_id,city,statistic_date,stu_num,class_room_num,sign) values (1002,'北京','2024-05-22 00:00:00',10,20,1);

插入数据后,我们发现数据录错了,那能不能直接删除或者更新,最好不要,数据量极少的话可能没啥问题,但是在做数据量比较大的业务时候,很容易出问题,正确的姿势如下:

  • 将旧数据的sign标志位置为-1,因为我这里是根据时间定位的,所以直接根据statistic_date字段查出这段时间内的数据,先置为-1再插入,也可以用insert into xxx select …的形式直接在数据库层面处理。假设我这里已经查询出来旧数据,重新将sign置为-1后再插入数据库
insert into  test_table(pmp_id,city,statistic_date,stu_num,class_room_num,sign) values (1002,'北京','2024-05-22 00:00:00',10,20,-1);

数据查询的正确姿势

数据插入后,其实这时候是有两条数据,一个是sign = 1, 一条是sign = -1,那如果这时候用户直接查询数据不就查出来是错误的数据吗?因为clickhouse的数据合并不一定是马上就合并,因为合并是一个非常消耗性能的操作,所以他会在数据库使用频率较低的时候触发。下面是查询的正确姿势:

SELECT
	pmp_id,
	city,
	statistic_date,
	sum( stu_num * sign ) AS stu_num,
	sum( class_room_num * sign ) AS class_room_num 
GROUP BY
	pmp_id, city,statistic_date 
HAVING
	sum( sign ) > 0;

这里有个重要的注意点就是GROUP BY后面的字段必须要跟你建表时候的联合主键对应,不然你的数据聚合出来的结果大概率会有错误,尤其是你的数据反复清洗的时候,表里面会同时存在sign = 1和sign = -1的数据

温馨提醒:这里只是提供一个Demo,铁子们有时间最好看一下官方文档细品一下,clickhouse非常有用。技多不压身,多动手总是没错的。

容易踩坑的点

如果产品来了一个需求,要求加一个表示学生来源的字段source,并且要作为分组的字段之一,那历史数据怎么办呢?

有两种方式

  • 方式一
    创建关联进行关联,这个根据自己的业务需求和数据进行设计即可
  • 方式二
    重新创建一张新表,重新创建联合主键,把原来涉及这个表的查询的SQL全部改到这个表上面。为什么要讲这个呢,因为这里有一个坑点,就是上面说的,group by 字段,一定要把原来的group by 后面的字段改成最新联合主键,不然你聚合出来的数据肯定是不对的,尤其是当clickhouse数据触发合并的时候,你会一脸懵。
    在这里插入图片描述

写在最后

好了,今天的坑点就分享到这里,官方文档已经附在文中,好学的你可以尝试抽时间去了解一下,蛮有用的,尤其是我们自己的业务拉起来之后,数据查询速度的提升真的效果,也给我们的搞钱的公众号"韭盾"带来了很大的效益。今天的内容就是以上内容,最近忙着搞钱,文章很久没更新了,后面会加快补上,咱们下期再见。分享不易,觉得有用的话,帮忙三连一下哦,哈哈!谢过了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

做一枚快乐的程序员

觉得不错的话,可以点赞加关注哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值