clickHouse的SummingMergeTree引擎以及AggregatingMergeTree引擎使用介绍


一、1.SummingMergeTree介绍
求和引擎继承自 MergeTree。区别在于,当合并 SummingMergeTree 表的数据片段时,ClickHouse 会把所有具有相同主键的行合并为一行,该行包含了被合并的行中具有数值数据类型的列的汇总值。如果主键的组合方式使得单个键值对应于大量的行,则可以显著的减少存储空间并加快数据查询的速度。

2.建表语句

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

columns - 包含了将要被汇总的列的列名的元组。可选参数。
所选的列必须是数值类型,并且不可位于主键中。

3.示例

--本地表
create table temp.summing_table_test1 on cluster ck_cluster
(
v1 Int32,
v2 Int32,
name String,
total_date DateTime
) ENGINE = SummingMergeTree((v1,v2))
order by (name)
partition by toDate(total_date)
SETTINGS index_granularity = 8192;

--写入测试数据:

insert into temp.summing_table_test1
values (1,2,'a',now()),(2,2,'a',now()-1*60*60),(3,4,'b',now());

--查询数据:

SELECT *
FROM temp.summing_table_test1

Query id: 2da82c96-2a90-496a-83fe-8a6528ba336c

┌─v1─┬─v2─┬─name─┬──────────total_date─┐
│ 3 │ 4 │ a │ 2021-10-13 11:41:12 │
│ 3 │ 4 │ b │ 2021-10-13 11:41:12 │
└────┴────┴──────┴─────────────────────┘

二、1.AggregatingMergeTree 介绍
该表引擎继承自MergeTree,可以使用 AggregatingMergeTree 表来做增量数据统计聚合。如果要按一组规则来合并减少行数,则使用 AggregatingMergeTree 是合适的。AggregatingMergeTree是通过预先定义的聚合函数计算数据并通过二进制的格式存入表内。

是SummingMergeTree的加强版,SummingMergeTree能做的是对非主键列进行sum聚合,而AggregatingMergeTree则可以指定各种聚合函数。

2.建表语句

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

3.示例
背景:
我们需要通过uid来获取用户的昵称或者等级等属性,而宽表中虽然保存有这些属性,不过在宽表更新时,就不可用了。所以通过抽取宽表的用户属性,新建一张AggregatingMergeTree表,这样的好处就是可以将更新的用户属性以insert的方式达到update的效果。

--建表:

CREATE TABLE user_group_test.aggregating_table_test1 on cluster ck_cluster
(
`uid` Int64 COMMENT 'uid',
`nickname` AggregateFunction(argMaxIf, String, DateTime, UInt8) COMMENT '昵称',
`phone` AggregateFunction(argMaxIf, String, DateTime, UInt8) COMMENT '手机号码',
`experience_level` AggregateFunction(argMaxIf, String, DateTime, UInt8) COMMENT '经验等级'
)
ENGINE = ReplicatedAggregatingMergeTree('/clickhouse/user_group_test/tables/{shard}/aggregating_table_test1', '{replica}')
ORDER BY uid
SETTINGS index_granularity = 8192;

CREATE TABLE user_group_test.aggregating_table_test1_all on cluster ck_cluster
as user_group_test.aggregating_table_test1
ENGINE = Distributed('ck_cluster', 'user_group_test', 'aggregating_table_test1', intHash64(uid));

--使用聚合函数插入数据:

SELECT
uid,
argMaxIfState(nickName,regTime,nickName!='') nickName,
argMaxIfState(phone,regTime,phone!='') phone,
argMaxIfState(level,regTime,level!='') level
FROM default.dwd_user_wide_all where totalDate=yesterday()
group by uid limit 20;

--查询:

select uid,argMaxIfMerge(nickname),
argMaxIfMerge(experience_level)
from user_group_test.aggregating_table_test1_all
where uid=123456 group by uid;