clickhouse的MergeTree系列引擎ReplacingMergeTree和SummingMergeTree的深入理解

2022-04-25 09:27:38 浏览数 (1)

ReplacingMergeTree引擎 简介: 该引擎和 MergeTree 的不同之处在于它会删除排序键值相同的重复项。 数据的去重只会在数据合并期间进行。合并会在后台一个不确定的时间进行,因此你无法预先作出计划。有一些数据可能仍未被处理。尽管你可以调用 OPTIMIZE 语句发起计划外的合并,但请不要依靠它,因为 OPTIMIZE 语句会引发对数据的大量读写。

建表语句

代码语言:javascript复制
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
 name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
 name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
 ...
) ENGINE = ReplacingMergeTree([ver])
[PARTITION BY expr]
[ORDER BY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]
  • ENGINE:引擎名和参数。
  • ver:版本列,类型可以是UInt*,Date,或者DateTime,可选择的参数。合并的时候ReplacingMergeTree从相同的主键中选择一行保留,如果ver列未指定,则选择最后一条,如果ver列已指定,则选择ver值最大的版本。
  • PARTITION BY:分区键。要按月分区,可以使用表达式 toYYYYMM(date_column) ,这里的 date_column 是一个 Date 类型的列。这里该分区名格式会是 “YYYYMM” 这样。
  • ORDER BY:表的排序键。可以是一组列或任意的表达式。例如: ORDER BY (CounterID, EventDate) 。
  • SAMPLE BY :抽样的表达式。如果要用抽样表达式,主键中必须包含这个表达式。例如:SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID)) 。
  • SETTINGS :影响 MergeTree 性能的额外参数:
    1. index_granularity 索引粒度。即索引中相邻『标记』间的数据行数。默认值,8192 。该列表中所有可用的参数可以从这里查看 MergeTreeSettings.h 。
    2. use_minimalistic_part_header_in_zookeeper — 数据片段头在 ZooKeeper 中的存储方式。如果设置了 use_minimalistic_part_header_in_zookeeper=1,ZooKeeper 会存储更少的数据。
    3. min_merge_bytes_to_use_direct_io 使用直接 I/O 来操作磁盘的合并操作时要求的最小数据量。合并数据片段时,ClickHouse 会计算要被合并的所有数据的总存储空间。如果大小超过了 min_merge_bytes_to_use_direct_io 设置的字节数,则 ClickHouse 将使用直接 I/O 接口(O_DIRECT 选项)对磁盘读写。如果设置 min_merge_bytes_to_use_direct_io = 0 ,则会禁用直接 I/O。默认值:10 1024 1024 * 1024 字节。

以上为建表参数描述,和MergeTree 相同,ver参数是本章重点。

下面我们来看案例:

代码语言:javascript复制
CREATE TABLE mytest.ReplacingMergeTreeTest  on cluster default( id UInt8, age UInt8, name String) ENGINE =ReplacingMergeTree(age) PARTITION BY id ORDER BY id

# 分布式表
CREATE TABLE mytest.ReplacingMergeTreeTestAll on cluster defaultas mytest.ReplacingMergeTreeTest ENGINE =Distributed('default','mytest','ReplacingMergeTreeTest', rand());

插入数据:

代码语言:javascript复制
# 下面是第一个节点
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(1,25,'张三');
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(1,22,'李四');
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(2,25,'张三1');
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(3,22,'李四1');
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(4,25,'张三2');
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(5,22,'李四3');

#第二个节点
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(6,22,'李四4');
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(5,22,'李四5');
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(1,29,'李四8');
insert into mytest.ReplacingMergeTreeTest(id,age,name) values(5,28,'李四9');
代码语言:javascript复制
执行optimize之后
OPTIMIZE TABLE mytest.ReplacingMergeTreeTest on cluster default

查询结果如下:


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

建表语句

代码语言:javascript复制
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 - 包含了将要被汇总的列的列名的元组。可选参数。所选的列必须是数值类型,并且不可位于主键中。如果没有指定 columns,ClickHouse 会把所有不在主键中的数值类型的列都进行汇总。

以上为建表参数描述,和MergeTree 相同,columns参数是本章重点。

下面我们来看案例 新建表

代码语言:javascript复制
CREATE TABLE mytest.SummingMergeTreeTest on cluster default( id UInt32, name String, money UInt32) ENGINE =SummingMergeTree(money) ORDER BY id

# 分布式表
CREATE TABLE mytest.SummingMergeTreeTestAll on cluster defaultas mytest.SummingMergeTreeTest ENGINE =Distributed('default','mytest','SummingMergeTreeTest', rand());

插入数据

代码语言:javascript复制
节点1
insert into SummingMergeTreeTest(id,name,money) values(1,'张三',1);
insert into SummingMergeTreeTest(id,name,money) values(1,'张三',1);
insert into SummingMergeTreeTest(id,name,money) values(1,'张三',1);
insert into SummingMergeTreeTest(id,name,money) values(2,'李四',1);

节点2
insert into SummingMergeTreeTest(id,name,money) values(1,'张三',1);
insert into SummingMergeTreeTest(id,name,money) values(1,'张三',1);
insert into SummingMergeTreeTest(id,name,money) values(2,'李四',1);
insert into SummingMergeTreeTest(id,name,money) values(2,'李四',1);

执行optmize

代码语言:javascript复制
OPTIMIZE TABLE mytest.SummingMergeTreeTest on cluster default;

从一个节点查询分布式结果如下:

总结:

  • ReplacingMergeTree引擎能从一定程度上解决数据表中字段唯一值问题。
  • SummingMergeTree引擎主要是处理合并数据集的问题。
  • OPTIMIZE只能针对于单个节点进行合并数据,不能针对于集群中数据。
  • final的使用只能针对于单节点的合并功能。

0 人点赞