clickhouse21.7.11.3 表引擎-SummingMergeTree

说明

按照 order by 字段聚合求和,其他列按照顺序 保留第一行

优点

如果主键的组合方式使得单个键值对应于大量的行,则可以 显著的减少存储空间 并 加快数据查询的速度。

聚合时机

  • 合并临时分区时,合并时机见 链接
  • 手动合并临时分区

聚合范围

在分区内部聚合求和,不能跨分区聚合求和

应用场景

不关注每一行详细记录,只关注求和结果

语法

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, ...]

解释:

  • SummingMergeTree([columns]) 括号内指定 求和的列。如果不指定,则所有非维度列且为数字类型的字段,汇总求和

  • order by 的列作为维度列,根据该列进行求和

  • partition by:根据该字段进行分区,对分区内进行 上面的 求和操作。不能跨分区求和

其他列按照顺序 保留第一行

案例

建表

create table t_order_smt(
    id UInt32 COMMENT '主键',
    sn String COMMENT '订单编号',
    total Decimal(11,2) COMMENT '总金额',
    create_time Datetime COMMENT '创建时间'
)
engine=SummingMergeTree(total)
partition by toYYYYMMDD(create_time)
primary key(id)
order by (id, sn);

解释:

  • SummingMergeTree(total) ... order by (id, sn);:id、sn 相同的记录,对这些记录的 total 列进行求和

  • partition by toYYYYMMDD(create_time):根据 create_time 的 YYYYMMDD 部分进行分区,对分区内进行 上面的 求和操作。不能跨分区求和

其他列按照顺序 保留第一行

第一次插入数据

insert into t_order_smt values
(1,'0001',100,'2022-01-01 11:20:00'),
(2,'0002',200,'2022-01-02 11:30:00'),
(1,'0001',100,'2022-01-01 11:10:00'),
(3,'0003',300,'2022-01-03 10:00:00'),

查询:

select * from t_order_smt

结果如下:

id sn total create_time
1 0001 200.00 2022-01-01 11:20:00
2 0002 200.00 2022-01-02 11:30:00
3 0003 300.00 2022-01-03 10:00:00

结论

1,'0001',100,'2022-01-01 11:10:00' 和 (1,'0001',100,'2022-01-01 11:10:00') 记录汇总求和了

最终保留:1|0001|200.00|2022-01-01 11:20:00|记录

原因

  • 下面两条数据,id、sn都相同,而且都是 2022-01-01 分区的数据,所以汇总求和
  • 其他列按照顺序 保留第一行(先插入的数据,排第一)
1,'0001',100,'2022-01-01 11:20:00'
1,'0001',100,'2022-01-01 11:10:00'

第二次插入数据

insert into t_order_rmt values
(1,'0001',100,'2022-01-01 11:20:00'),
(2,'0002',200,'2022-01-02 11:30:00'),
(1,'0001',100,'2022-01-01 11:10:00'),
(3,'0003',300,'2022-01-03 10:00:00'),

查询:

select * from t_order_rmt

结果如下:

id|sn  |total |create_time        |
--|----|------|-------------------|
 1|0001|200.00|2022-01-01 11:20:00|
 1|0001|200.00|2022-01-01 11:20:00|
 2|0002|200.00|2022-01-02 11:30:00|
 2|0002|200.00|2022-01-02 11:30:00|
 3|0003|300.00|2022-01-03 10:00:00|
 3|0003|300.00|2022-01-03 10:00:00|

结论

没有汇总求和

原因

第二次插入数据,不会自动汇总求和

当 临时分区合并 时,才会汇总求和

再连续执行 4次 插入数据

会触发 临时分区合并,再次查询,结果如下:

id|sn  |total  |create_time        |
--|----|-------|-------------------|
 1|0001|1000.00|2022-01-01 11:20:00|
 2|0002|1000.00|2022-01-02 11:30:00|
 3|0003|1500.00|2022-01-03 10:00:00|

案例-分区间不能汇总求和

重新建表进行测试

删除表

DROP table t_order_smt

创建表

create table t_order_smt(
    id UInt32 COMMENT '主键',
    sn String COMMENT '订单编号',
    total Decimal(11,2) COMMENT '总金额',
    create_time Datetime COMMENT '创建时间'
)
engine=SummingMergeTree(total)
partition by toYYYYMMDD(create_time)
primary key(id)
order by (id, sn);

插入数据

插入5次数据

insert into t_order_smt values
(1,'0001',100,'2022-01-01 11:20:00'),
(1,'0001',100,'2022-01-04 11:10:00'),

查询结果如下:

id sn total create_time
1 0001 500.00 2022-01-01 11:20:00
1 0001 500.00 2022-01-04 11:10:00

在合并时,会 汇总求和,但 上面两条数据,在根据 create_time 的 YYYYMMDD 部分,分散在 2022-01-01 和 2022-01-04 2个分区,分区间的数据,不会汇总求和

案例-手动合并临时分区,汇总求和

执行下面语句,立即合并分区,汇总求和

注意:只能分区内合并

optimize table t_order_smt  final;

引用:
https://blog.csdn.net/liuyingying0418/article/details/121547844


原文出处:/show_1IX3Q4blctbK.html