MergeTree系列的表引擎时ClickHouse数据存储功能的核心。他们提供了用于弹性和高性能数据检索的大多数功能:列存储,自定义区分,稀疏的主索引,辅助数据跳过索引等。 基本MergeTree表引擎可以被认为时单节点ClickHouse实例的默认表引擎,因为它在各种用例中通用且实用。
对于生产用途,ReplicatedMergeTree时必经之路,因为它为常规MergeTree引擎的所有功能增加了高可用性。一个额外的好处是在数据提取时自动进行重复数据删除。,因此如果插入过程中出现网络问题,该软件可以安全地重试。
MergeTree系列的所有其他引擎为某些特定用例添加了额外的功能。通常,它是作为后台的其他数据操作实现的。
MergeTree引擎的主要缺点是他们很重。因此,典型的模式没有太多。如果需要许多小表(例如用于临时数据),考虑使用Log engine family。
- 允许快速写入不断变化的对象状态
- 删除后台中的旧对象状态。这显著降低了存储体积。
MergeTree结构的优点
- 数据的更新
- 数据的排序
- 快速查询
- 建立索引
- 分区
- 自动的合并 -> 去重 局部聚合
建表基本格式
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster](
name1 [type1] [DEFAULT | MATERIALIZED | ALIAS expr1] [TTL expr1],
name1 [type1] [DEFAULT | MATERIALIZED | ALIAS expr1] [TTL expr1],
...
INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2
) ENGINE = MergeTree()ORDER BY expr[PARTITION BY expr][PRIMARY KEY expr] [TTL expr [DELETE|TO DISK 'xxx'| TO VOLUME 'xxx'], ...][SETTINGS name=value, ...]
参数解读
ENGINE - 引擎的名称和参数。ENGINE= MergeTree()。该MergeTree引擎没有参数。
ORDER BY - 排序键
列名称或任意表达式的元组。范例:ORDER BY(CounterID, EventDate)。
如果PRIMARY KEY子句未明确定义主键,则ClickHouse会将排序键用作主键。
ORDER BY tuple()如果不需要排序,请使用语法。
PARTITION BY - 分区键。可选的。
要按月进行分区,请使用toYYYYMM(date_column)表达式,其中的date_column是日期类型为Date的列。此处的分区名称具有“YYYYMM”格式。
PRIMARY KEY - 主键(与排序键)不同,可选的。
默认情况下,主键与排序键(由ORDER BY子句指定)相同。因此,在大多数情况下,无需指定单独的PRIMARY KEY子句。
SAMPLE BY - 用于采用的表达式。可选的。
如果使用采样表达式,则主键必须包含它,范例:SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))。
TTL-规则列表,用于指定行的存储持续时间并定义磁盘和卷之间零件自动移动的逻辑。可选的。结果必须由一个Date或DateTime列。例子 TTL data + INTERVAL 1DAY
SETTINGS - 控制MergeTree(可选)行为的其他参数
- index_granularity - 索引标记之间的最大数据行数。默认值:8192。
- index_granularity_bytes - 数据粒度的最大大小(以字节为单位)。默认值:10Mb。要仅按行数限制颗粒大小,请设置为0(不建议)。
- enable_mixed_granularity_pards - 启用或警用过度以通过index_granularity_bytes设置控制颗粒尺寸。在版本19.11之前,只有index_granularity用于限制颗粒大小的设置。index_granularity_bytes从具有大行(数十和数百MB)的表中选择数据时,此设置可提高ClickHouse性能。
use_mininalistic_part_header_in_zookeeper - ZooKeeper中数据不见头的存储方法。如果为use_minimalistic_part_header_in_zookeeper=1,则ZooKeeper存储的数据较少。
min_merge_bytes_to_use_direct_io - 使用对存储磁盘的直接I/O访问所需的最小合并操作数据量。合并数据部分时,ClickHouse会计算要合并的所有数据的总存储量。如果卷超过min_merge_bytes_to_use_direct_io字节,ClickHouse将使用直接I/O接口读取数据并将数据写入磁盘。如果为mini_merge_bytes_to_use_direct_io = 0,则直接I/O被禁用,默认值:1010241024*1024字节。
CREATE TABLE tb_mt
(
`id` Int8,
`name` String,
`addr` String
)
ENGINE = MergeTree()
ORDER BY id
insert into tb_mt values (1, 'zs','bj'), (5, 'ls','nj');
insert into tb_mt values(2, 'ww', 'SH'), (3, 'zl', 'dj');
指定分区
CREATE TABLE tb_mt2
(
`id` Int8,
`name` String,
`addr` String
)
ENGINE = MergeTree()
PARTITION BY addr
ORDER BY id
;
insert into tb_mt2 values (1, 'zs','bj'), (5, 'ls','nj');
insert into tb_mt2 values(2, 'ww', 'nj'), (3, 'zl', 'bj');
ReplacingMergeTree
这个引擎是在MergeTree的基础上,添加了“处理重复数据”的功能,该引擎和MergeTree的不同之处在于他会删除具有相同主键的重复项。数据的去重只会在合并的过程中出现。 合并会在未知的时间在后台进行,所以你会无法预先做出计划。由一些数据可能仍未被处理。因此,ReplacingMergeTree适用于在后台清楚重复的数据以节省空间,但是它不保证没有重复的数据出现。
创建表
CREATE TABLE TB_REP_MERGE_TREE (
id Int8,
name String,
ctime Date,
version UInt8
)
engine=ReplacingMergeTree(vertion)
order by id
CollapsingMergeTree
ClickHouse实现了CollapsingMergeTree来消除ReplacingMergeTree的限制(只删除小版本字段的问题,只保留最大数据版本)。该引擎要求在建表语句中指定一个标记列Sign,后台Compaction时会将主键相同、Sign相反的行进行折叠,也即删除。
每次需要新增状态时,写入一行状态行:需要删除状态时,则写入一行取消行。
由于后台Campaction时机无法预测,在发起查询时,状态行和取消行可能尚未被折叠;另外,ClickHouse无法保证primary key相同的行落在同一个节点上,不在同一节点上的数据无法折叠。因此在进行count(*)、sum(col)等聚合计算时,可能会存在数据冗余的情况。为了获得正确的结果,所以一般不太使用
VersionedCollapsingMergeTree
取消字段和数据版本同时使用,避免取消行数据无法删除的问题 创建表
CREATE TABLE tb_vs_cpl_mt
(
uid UInt64,
name String,
age UInt8,
sign Int8,
version UInt8
)
ENGINE = VersionedCollapsingMergeTree(sign, version)
ORDER BY uid;
INSERT INTO tb_vs_cpl_mt VALUES (1001, 'ADA', 18, -1, 1), (1001, 'ADA', 18, -1, 1);
INSERT INTO tb_vs_cpl_mt VALUES (1001, 'ADA', 19, 1, 3);
INSERT INTO tb_vs_cpl_mt VALUES (1001, 'ADA', 19, -1, 3);
SummingMergeTree
该引擎继承自MergeTree,区别在于,当合并SummingMergeTree表的数据片段时,ClickHouse会把所有具有相同主键的合并为一行,该行包含了被合并的行中具有数值类型的列的汇总值。如果主键的组合方式是的单个键值对应大于大量的行,则可以显著的减少存储弓箭并加快数据查询的速度,对于不可加的列,会去一个最优先出现的值。
创建表
CREATE TABLE tb_summ_merge_mt4
(
id Int8,
name String,
age Int8,
cost UInt64
)
ENGINE = SummingMergeTree(cost)
ORDER BY id
PARTITION BY name
PRIMARY KEY id;
insert into tb_summ_merge_mt4 values (1, 'a', 20, 10);
insert into tb_summ_merge_mt4 values (1, 'b', 30, 20);
insert into tb_summ_merge_mt4 values (1, 'a', 20, 30);