前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >大数据ClickHouse(十二):MergeTree系列表引擎之CollapsingMergeTree

大数据ClickHouse(十二):MergeTree系列表引擎之CollapsingMergeTree

原创
作者头像
Lansonli
发布2022-08-28 00:55:06
7170
发布2022-08-28 00:55:06
举报
文章被收录于专栏:Lansonli技术博客

MergeTree系列表引擎之CollapsingMergeTree

一、CollapsingMergeTree基本讲解

CollapsingMergeTree就是一种通过以增代删的思路,支持行级数据修改和删除的表引擎。它通过定义一个sign标记位字段,记录数据行的状态。如果sign标记为1,则表示这是一行有效的数据;如果sign标记为-1,则表示这行数据需要被删除。当CollapsingMergeTree分区合并时,同一数据分区内,sign标记为1和-1的一组数据会被抵消删除。

每次需要新增数据时,写入一行sign标记为1的数据;需要删除数据时,则写入一行sign标记为-1的数据。此外,只有相同分区内的数据才有可能被折叠。

  • CollapsingMergeTree建表语法如下:
代码语言:javascript
复制
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
sign Int8
) ENGINE = CollapsingMergeTree(sign)
[PARTITION BY expr]
[ORDER BY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]

存在的问题:

CollapsingMergeTree对于写入数据的顺序有着严格要求,否则导致无法正常折叠。

数据折叠保留规则:

在同一个分区内order by 字段相同的数据存在多条,且sign值不同,数据保留规则如下:

  • 如果sign=1和sign=-1的行数相同并且最后一行数据sign=1,则保留第一行sign=-1的行和最后一行sign=1的行。
  • 如果sign=1的行比sign=-1的行多,则保留最后一条sign=1的行。
  • 如果sign=-1的行比sign=1的行多,则保留第一条sign=-1的行。
  • 其他情况,不保留数据。

二、测试实例

1、按照顺序写入需要更新或删除的数据

代码语言:javascript
复制
#创建表 t_collapsing_mt ,使用CollapsingMergeTree
node1 :) create table t_collapsing_mt(
:-] id UInt8,
:-] name String,
:-] loc String,
:-] login_times UInt8,
:-] total_dur UInt8,
:-] sign Int8
:-] )engine = CollapsingMergeTree(sign)
:-] order by (id,total_dur)
:-] primary key id
:-] partition by loc
:-] ;

#向表   t_collapsing_mt 中插入以下数据:
node1 :) insert into t_collapsing_mt values(1,'张三','北京',1,30,1),(2,'李四','上海',1,40,1)

#查看表 t_collapsing_mt中的数据
node1 :) select * from t_collapsing_mt;
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  2 │ 李四 │ 上海 │           1 │        40 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  1 │ 张三 │ 北京 │           1 │        30 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘

#向表 t_collapsing_mt中继续插入一条数据,删除“张三”数据
node1 :) insert into t_collapsing_mt values(1,'张三','北京',1,30,-1);

#查询表 t_collapsing_mt 中的数据 
node1 :) select * from t_collapsing_mt;
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  1 │ 张三 │ 北京 │           1 │        30 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  2 │ 李四 │ 上海 │           1 │        40 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  1 │ 张三 │ 北京 │           1 │        30 │    -1│
└────┴──────┴──────┴─────────────┴───────────┴──────┘

#手动触发 optimize 合并相同分区数据
node1 :) optimize table t_collapsing_mt;

#查询表 t_collapsing_mt 中的数据 
node1 :) select * from t_collapsing_mt;
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  2 │ 李四 │ 上海 │           1 │        40 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘


#插入以下两条数据,来更新 “李四”数据
node1 :) insert into t_collapsing_mt values(2,'李四','上海',1,40,-1),(2,'李四','上海',2,100,1);

#查询表 t_collapsing_mt 中的数据 
node1 :) select * from t_collapsing_mt;
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  2 │ 李四 │ 上海 │           1 │        40 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  2 │  李四│ 上海 │           1 │        40 │   -1 │
│  2 │  李四│ 上海 │           2 │       100 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘

#手动执行 optimize 触发相同分区合并
node1 :) optimize table t_collapsing_mt;

#查看表 t_collapsing_mt中的数据
node1 :) select * from t_collapsing_mt;
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  2 │ 李四 │ 上海 │           2 │       100 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘

注意:以上功能使用 collapsingMergeTree实现了分区合并。

2、乱序写入需要更新或删除的数据

代码语言:javascript
复制
#删除表 t_collapsing_mt ,重新创建表 t_collapsing_mt
这里建表语句与之前一样

#向表 t_collapsing_mt 中插入以下数据:
node1 :) insert into t_collapsing_mt values(1,'张三','北京',1,30,-1),(1,'张三','北京',1,30,1),(2,'李四','上海',1,40,1)

#查询表 t_collapsing_mt中的数据
node1 :) select * from t_collapsing_mt;
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  2 │ 李四 │ 上海 │           1 │        40 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  1 │ 张三 │ 北京 │           1 │        30 │   -1 │
│  1 │ 张三 │ 北京 │           1 │        30 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘

#手动执行 optimize 命令,合并相同分区数据
node1 :) optimize table t_collapsing_mt;

#查询表 t_collapsing_mt表中的数据,数据没有变化
node1 :) select * from t_collapsing_mt;
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  2 │ 李四 │ 上海 │           1 │        40 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘
┌─id─┬─name─┬─loc──┬─login_times─┬─total_dur─┬─sign─┐
│  1 │ 张三 │ 北京 │           1 │        30 │   -1 │
│  1 │ 张三 │ 北京 │           1 │        30 │    1 │
└────┴──────┴──────┴─────────────┴───────────┴──────┘

注意:当数据插入到表中的顺序标记如果不是1,-1这种顺序时,合并相同分区内的数据不能达到修改和更新效果。

如果数据的写入程序是单线程执行的,则能够较好地控制写入顺序;如果需要处理的数据量很大,数据的写入程序通常是多线程执行的,那么此时就不能保障数据的写入顺序了。在这种情况下,CollapsingMergeTree的工作机制就会出现问题。但是可以通过VersionedCollapsingMergeTree的表引擎得到解决。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ​MergeTree系列表引擎之CollapsingMergeTree
    • 一、CollapsingMergeTree基本讲解
      • 二、测试实例
        • 1、按照顺序写入需要更新或删除的数据
        • 2、乱序写入需要更新或删除的数据
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档