clickhouse中使用ReplacingMergeTree表引擎
2022-03-19
张子阳
分类: 大数据处理
在上一篇文章 clickhouse中使用Join表引擎 中,我们利用Join表引擎自动排重的特性,实现了在数据插入过程中,基于某些字段只取首行。常见的使用场景,例如:针对用户订单表,查询:用户的首次付款金额、首次订单号。但Join表无法实现取最后一行,例如用户最后一次付款金额、最后一次订单号。这篇文章介绍使用使用ReplacingMergeTree表引擎,来获取最后一次数据插入的行。
准备工作
和前一章类似,我们先做一些数据准备,创建一张基础数据表,user_order用户订单表:
drop table if exists user_order; create table user_order ( user_id String, // 用户ID event_date String, // 付款日期 order_no String, // 订单号 amount Int32 // 金额 ) ENGINE = MergeTree() ORDER BY (user_id, event_date)
创建基于ReplacingMergeTree表引擎的物化视图
ReplacingMergeTree表引擎,可以基于排序列进行去重,但是和Join的去重模式不同,它会用最后一次接收的值,去覆盖前面的值。利用这一特性,就可以实现“获取分组后的最后一行数据”这一效果。
drop view if exists user_order_r; CREATE MATERIALIZED VIEW user_order_r ENGINE = ReplacingMergeTree() ORDER BY(user_id) POPULATE AS select user_id, event_date, order_no, amount from user_order
接下来,插入测试数据:
insert into user_order(user_id, event_date, order_no, amount) values('user1', '2022-01-01', 'B', 4); insert into user_order(user_id, event_date, order_no, amount) values('user1', '2022-01-02', 'C', 8); insert into user_order(user_id, event_date, order_no, amount) values('user1', '2022-01-03', 'A', 2);
插入完成后,如果立即对 user_order_r 进行查询,会发现三条数据都存在,这是因为ReplacingMergeTree引擎和AggregatingMergeTree类似,并不是实时执行数据的合并和替换的,而是会有一个不确定的时滞。所以它只是部分地实现了“获取分组最后一行”的效果。
因此,对于user_order_r,还需要进行二次处理,去除重复项。具体的实现方式,可以参考 clickhouse选取group后的首末行。这里我们使用最为简便的AnyLast()函数。
创建user_order_v视图
drop view if exists user_order_v; CREATE VIEW user_order_v AS select user_id, anyLast(event_date) event_date, anyLast(order_no) order_no, anyLast(amount) amount from (select * from user_order order by user_id, event_date) group by user_id
这里没有再次创建物化视图,因为数据查询的是 user_order_r,在经历过ReplacingMergeTree合并之后,数据量级通常会缩小很多,优于直接对原始的user_order进行查询。
感谢阅读,希望这篇文章能给你带来帮助!