今天说下clickhouse的另一个表引擎SummingMergeTree。
一看名称,我们应该能够猜到,这是一个什么类型的引擎,对,是一个后台根据主键做数据聚合的引擎。
来看一段官方的解释:
该引擎继承自MergeTree,区别在于,当合并SummingMergeTree表的数据片段时,Clickhouse会把所有相同主键的行,合并为一行,该行包含了被合并的所有行中具有数值类型的列的汇总值。如果主键的组合方式使得单个键值对应大量的行,则可以显著减少存储空间,并加快数据查询的速度。
我们推荐该引擎与MergeTree一起使用。例如在准备做报告的时候,将完整的数据存储在MergeTree表中,并且使用SummingMergeTree来存储聚合数据。这种方法可以避免因为你使用不恰当的主键组合方式而导致的有价值的数据丢失。
建表
1 | CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] |
SummingMergeTree的参数
- columns,包含了将要被汇总的列的元祖集合。可选参数。
所选的列必须是数值类型,并且不能在主键中
实例
1 | -- 建表 |
当然clickhouse可能不会完整地汇总所有行,查询的时候我们可以使用groupby方式得到正确的聚合结果。
1 | select key, sum(value) from summtt group by key; |
数据处理
当数据插入到表中时,它们会被原样保存,clickhouse定期合并插入的数据片段,并且在这个时候对所有具有相同主键的行中的列进行汇总,将这些行替换为包含汇总数据的一行记录。
clickhouse会按片段进行数据合并,以至于不同片段中会包含有相同主键的行,即单个汇总片段将会是不完整的,因此聚合函数sum()和groupby子句应该在select查询语句中被使用。
汇总的通用规则
列中数值类型的字段会被汇总,这些列的集合应该在columns元祖中被定义。
如果用于汇总的所有列中的值均为0,则该行会被删除。
如果列不在汇总列和主键中,则会在现有的值中任选一个。
主键所在的列的值不会被汇总。
AggregateFunction列中的汇总
对于AggregateFunction的列,clickhouse会根据对应函数表现为AggregateMergeTree引擎的聚合操作。
嵌套结构
表中可以存在具有以特殊方式处理的嵌套数据结构。
如果嵌套表的名称以Map结尾,并且包含至少两个符合以下条件的列:
- 第一列是数值类型(Int, Date, DateTime),我们称之为Key;
- 其他的列是可计算的(Int, Float32/64),我们称之为values(values…)
- 然后这个嵌套表会被解释为一个key -> (values…)的映射,当合并他们的行时,两个数据集中的元素,会根据key合并为(values…)的汇总值;
例如:1
2
3
4[(1, 100)] + [(2, 150)] -> [(1, 100), (2, 150)]
[(1, 100)] + [(1, 150)] -> [(1, 250)]
[(1, 100)] + [(1, 150), (2, 150)] -> [(1, 250), (2, 150)]
[(1, 100), (2, 150)] + [(1, -100)] -> [(2, 150)]
请求数据时,通过sumMap(key, values)函数来对map进行聚合。
对于嵌套数据结构,你无需在列的元祖中指定列以进行汇总。
Keep reading, Keep writing, Keep coding.
欢迎关注我的微信公众号,比较喜欢分享知识,也喜欢宠物,所以做了这2个公众号:
喜欢宠物的朋友可以关注:【电巴克宠物Pets】
一起学习,一起进步。
