文章目录
MergeTree系列表引擎之CollapsingMergeTree
CollapsingMergeTree就是一种通过以增代删的思路,支持行级数据修改和删除的表引擎。它通过定义一个sign标记位字段,记录数据行的状态。如果sign标记为1,则表示这是一行有效的数据;如果sign标记为-1,则表示这行数据需要被删除。当CollapsingMergeTree分区合并时,同一数据分区内,sign标记为1和-1的一组数据会被抵消删除。
每次需要新增数据时,写入一行sign标记为1的数据;需要删除数据时,则写入一行sign标记为-1的数据。此外,只有相同分区内的数据才有可能被折叠。
- 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值不同,数据保留规则如下:
- #创建表 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实现了分区合并。
- #删除表 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的表引擎得到解决。