目录
5 VersionedCollapsingMergeTree 引擎
7.1.2 建一个AggregatingMergeTree引擎表引擎表
7.2 AggregatingMergeTree引擎物化视图
1 clickhouse表引擎-合并树系列简介
Clickhouse 中最强大的表引擎当属 MergeTree
(合并树)引擎及该系列(*MergeTree
)中的其他引擎。MergeTree
系列的引擎被设计用于插入极大量的数据到一张表当中。数据可以以数据片段的形式一个接着一个的快速写入,数据片段在后台按照一定的规则进行合并。相比在插入时不断修改(重写)已存储的数据,这种策略会高效很多。
主要特点:
① 存储的数据按主键排序。这使得你能够创建一个小型的稀疏索引来加快数据检索。
② 支持数据分区,如果指定了 分区键 的话。在相同数据集和相同结果集的情况下 ClickHouse 中某些带分区的操作会比普通操作更快。查询中指定了分区键时 ClickHouse 会自动截取分区数据。这也有效增加了查询性能。
③ 支持数据副本。ReplicatedMergeTree
系列的表提供了数据副本功能。更多信息,请参阅 数据副本 一节。
④ 支持数据采样。需要的话,你可以给表设置一个采样方法。
2 MergeTree引擎
2.1 建表语法
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],
...
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]
[SAMPLE BY 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
子句。用于指定表数据以何种标准进行分区。分区键可以单个列字段,也可以是通过元祖形式使用的多个列字段,还可以支持使用列表达式。若不声明分区键则clickhouse会生成一个名为all的分区。合理使用分区 可以有效减少查询数据文件的扫描范围。
⑤ SAMPLE BY
— 用于抽样的表达式。如果要用抽样表达式,主键中必须包含这个表达式。例如:SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))
。
⑥ TTL 指定行存储的持续时间并定义数据片段在硬盘和卷上的移动逻辑的规则列表,可选。表达式中必须存在至少一个 Date
或 DateTime
类型的列,比如:TTL date + INTERVAl 1 DAY
规则的类型 DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'
指定了当满足条件(到达指定时间)时所要执行的动作:移除过期的行,还是将数据片段(如果数据片段中的所有行都满足表达式的话)移动到指定的磁盘(TO DISK 'xxx'
) 或 卷(TO VOLUME 'xxx'
)。默认的规则是移除(DELETE
)。可以在列表中指定多个规则,但最多只能有一个DELETE
的规则。更多细节,请查看 表和列的 TTL
⑦ SETTINGS
— 控制 MergeTree
行为的额外参数:
index_granularity
— 索引粒度。索引中相邻的『标记』间的数据行数。默认值,8192 。参考数据存储。index_granularity_bytes
— 索引粒度,以字节为单位,默认值: 10Mb。如果想要仅按数据行数限制索引粒度, 请设置为0(不建议)。enable_mixed_granularity_parts
— 是否启用通过index_granularity_bytes
控制索引粒度的大小。在19.11版本之前, 只有index_granularity
配置能够用于限制索引粒度的大小。当从具有很大的行(几十上百兆字节)的表中查询数据时候,index_granularity_bytes
配置能够提升ClickHouse的性能。如果你的表里有很大的行,可以开启这项配置来提升SELECT
查询的性能。use_minimalistic_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 接口(O_DIRECT
选项)对磁盘读写。如果设置min_merge_bytes_to_use_direct_io = 0
,则会禁用直接 I/O。默认值:10 * 1024 * 1024 * 1024
字节。merge_with_ttl_timeout
— TTL合并频率的最小间隔时间,单位:秒。默认值: 86400 (1 天)。write_final_mark
— 是否启用在数据片段尾部写入最终索引标记。默认值: 1(不建议更改)。merge_max_block_size
— 在块中进行合并操作时的最大行数限制。默认值:8192storage_policy
— 存储策略。 参见 使用具有多个块的设备进行数据存储.min_bytes_for_wide_part
,min_rows_for_wide_part
在数据片段中可以使用Wide
格式进行存储的最小字节数/行数。你可以不设置、只设置一个,或全都设置。参考:数据存储
2.2 创建最简单的MergerTree引擎表
建表语句
create table tb_test_MergeTree(`id` Int64,`vipId` Int64,`brandId` Int32,`shopId` Int32, `saleDate` Date,saleMoney Float32) engine = MergeTree() ORDER BY (brandId,shopId)
执行
b64d9704419c :) create table tb_test_MergeTree(`id` Int64,`vipId` Int64,`brandId` Int32,`shopId` Int32, `saleDate` Date,saleMoney Float32) engine = MergeTree() ORDER BY (brandId,shopId)
CREATE TABLE tb_test_MergeTree
(
`id` Int64,
`vipId` Int64,
`brandId` Int32,
`shopId` Int32,
`saleDate` Date,
`saleMoney` Float32
)
ENGINE = MergeTree()
ORDER BY (brandId, shopId)
Ok.
0 rows in set. Elapsed: 0.044 sec.
b64d9704419c :)
查看
b64d9704419c :) show tables;
SHOW TABLES
┌─name──────────────┐
│ tb_test_Log │
│ tb_test_MergeTree │
│ tb_test_StripeLog │
│ tb_test_TinyLog │
└───────────────────┘
4 rows in set. Elapsed: 0.003 sec.
b64d9704419c :) show create table tb_test_MergeTree
SHOW CREATE TABLE tb_test_MergeTree
┌─statement───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ CREATE TABLE liucf_ch_db.tb_test_MergeTree (`id` Int64, `vipId` Int64, `brandId` Int32, `shopId` Int32, `saleDate` Date, `saleMoney` Float32) ENGINE = MergeTree() ORDER BY (brandId, shopId) SETTINGS index_granularity = 8192 │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
1 rows in set. Elapsed: 0.002 sec.
b64d9704419c :)
磁盘目录变化
2.3 插入数据
insert into tb_test_MergeTree values (10001,8001,429,6001,'2020-10-01 14:15:23',200.50)
insert into tb_test_MergeTree values (10002,8002,429,6001,'2020-10-02 14:15:23',300.50),(10003,8001,429,6001,'2020-10-02 14:15:23',100.50)
2.4 查看目录结构
tb_test_MergeTree
├── all_1_1_0
│ ├── brandId.bin
│ ├── brandId.mrk2
│ ├── checksums.txt
│ ├── columns.txt
│ ├── count.txt
│ ├── id.bin
│ ├── id.mrk2
│ ├── primary.idx
│ ├── saleDate.bin
│ ├── saleDate.mrk2
│ ├── saleMoney.bin
│ ├── saleMoney.mrk2
│ ├── shopId.bin
│ ├── shopId.mrk2
│ ├── vipId.bin
│ └── vipId.mrk2
├── detached
└── format_version.txt
可见建表是如果不指定PARTITION BY默认会生成一个all_x_x_x的分区
detached
目录存放着使用 DETACH 语句从表中卸载的片段。损坏的片段不会被删除而是也会移到该目录下。服务器不会去使用detached
目录中的数据片段。因此你可以随时添加,删除或修改此目录中的数据 – 在运行 ATTACH 语句前,服务器不会感知到。
查看元数据信息
b64d9704419c :) select * from parts where table='tb_test_MergeTree';
SELECT *
FROM parts
WHERE table = 'tb_test_MergeTree'
┌─partition─┬─name──────┬─part_type─┬─active─┬─marks─┬─rows─┬─bytes_on_disk─┬─data_compressed_bytes─┬─data_uncompressed_bytes─┬─marks_bytes─┬───modification_time─┬─────────remove_time─┬─refcount─┬───min_date─┬───max_date─┬────────────min_time─┬────────────max_time─┬─partition_id─┬─min_block_number─┬─max_block_number─┬─level─┬─data_version─┬─primary_key_bytes_in_memory─┬─primary_key_bytes_in_memory_allocated─┬─is_frozen─┬─database────┬─table─────────────┬─engine────┬─disk_name─┬─path──────────────────────────────────────────────────────────────┬─hash_of_all_files────────────────┬─hash_of_uncompressed_files───────┬─uncompressed_hash_of_compressed_files─┐
│ tuple() │ all_1_1_0 │ Wide │ 1 │ 2 │ 1 │ 491 │ 186 │ 30 │ 288 │ 2020-11-10 10:22:54 │ 0000-00-00 00:00:00 │ 1 │ 0000-00-00 │ 0000-00-00 │ 0000-00-00 00:00:00 │ 0000-00-00 00:00:00 │ all │ 1 │ 1 │ 0 │ 1 │ 16 │ 8192 │ 0 │ liucf_ch_db │ tb_test_MergeTree │ MergeTree │ default │ /var/lib/clickhouse/data/liucf_ch_db/tb_test_MergeTree/all_1_1_0/ │ 4905714359a76926feb423511f18d06f │ 24026952cca8ad85bb6b38798dac951a │ ed4f2b96eecf6163ce254fe3a95ee387 │
└───────────┴───────────┴───────────┴────────┴───────┴──────┴───────────────┴───────────────────────┴─────────────────────────┴─────────────┴─────────────────────┴─────────────────────┴──────────┴────────────┴────────────┴─────────────────────┴─────────────────────┴──────────────┴──────────────────┴──────────────────┴───────┴──────────────┴─────────────────────────────┴───────────────────────────────────────┴───────────┴─────────────┴───────────────────┴───────────┴───────────┴───────────────────────────────────────────────────────────────────┴──────────────────────────────────┴──────────────────────────────────┴───────────────────────────────────────┘
2.5 指定分区的 MergeTree 表
建表语句
create table tb_test_MergeTree_partitions(`id` Int64,`vipId` Int64,`brandId` Int32,`shopId` Int32, `saleDate` Date,saleMoney Float32) engine = MergeTree() ORDER BY (brandId,shopId) PARTITION BY (brandId,shopId)
执行建表
b64d9704419c :) create table tb_test_MergeTree_partitions(`id` Int64,`vipId` Int64,`brandId` Int32,`shopId` Int32, `saleDate` Date,saleMoney Float32) engine = MergeTree() ORDER BY (brandId,shopId) PARTITION BY (brandId,shopId)
CREATE TABLE tb_test_MergeTree_partitions
(
`id` Int64,
`vipId` Int64,
`brandId` Int32,
`shopId` Int32,
`saleDate` Date,
`saleMoney` Float32
)
ENGINE = MergeTree()
PARTITION BY (brandId, shopId)
ORDER BY (brandId, shopId)
Ok.
0 rows in set. Elapsed: 0.006 sec.
b64d9704419c :) show create table tb_test_MergeTree_partitions
SHOW CREATE TABLE tb_test_MergeTree_partitions
┌─statement──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ CREATE TABLE liucf_ch_db.tb_test_MergeTree_partitions (`id` Int64, `vipId` Int64, `brandId` Int32, `shopId` Int32, `saleDate` Date, `saleMoney` Float32) ENGINE = MergeTree() PARTITION BY (brandId, shopId) ORDER BY (brandId, shopId) SETTINGS index_granularity = 8192 │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
1 rows in set. Elapsed: 0.002 sec.
b64d9704419c :)
文件目录
[root@ds2 liucf_ch_db]# tree tb_test_MergeTree_partitions
tb_test_MergeTree_partitions
├── detached
└── format_version.txt
2.6 分区合并过程
插入数据
b64d9704419c :) insert into tb_test_MergeTree_partitions values (10001,8001,429,6001,'2020-10-01 14:15:23',200.50)
INSERT INTO tb_test_MergeTree_partitions VALUES
Ok.
1 rows in set. Elapsed: 0.003 sec.
b64d9704419c :) insert into tb_test_MergeTree_partitions values (10002,8002,429,6002,'2020-10-02 14:15:23',300.50),(10003,8001,429,6001,'2020-10-02 14:15:23',100.50)
INSERT INTO tb_test_MergeTree_partitions VALUES
Ok.
2 rows in set. Elapsed: 0.037 sec.
b64d9704419c :) select * from tb_test_MergeTree_partitions
SELECT *
FROM tb_test_MergeTree_partitions
┌────id─┬─vipId─┬─brandId─┬─shopId─┬───saleDate─┬─saleMoney─┐
│ 10003 │ 8001 │ 429 │ 6001 │ 2020-10-02 │ 100.5 │
└───────┴───────┴─────────┴────────┴────────────┴───────────┘
┌────id─┬─vipId─┬─brandId─┬─shopId─┬───saleDate─┬─saleMoney─┐
│ 10001 │ 8001 │ 429 │ 6001 │ 2020-10-01 │ 200.5 │
└───────┴───────┴─────────┴────────┴────────────┴───────────┘
┌────id─┬─vipId─┬─brandId─┬─shopId─┬───saleDate─┬─saleMoney─┐
│ 10002 │ 8002 │ 429 │ 6002 │ 2020-10-02 │ 300.5 │
└───────┴───────┴─────────┴────────┴────────────┴───────────┘
3 rows in set. Elapsed: 0.003 sec.
b64d9704419c :)
磁盘目录
可见分 2次插入3调数据,有3个分区,
[root@ds2 liucf_ch_db]# tree tb_test_MergeTree_partitions
tb_test_MergeTree_partitions
├── 429-6001_1_1_0
│ ├── brandId.bin
│ ├── brandId.mrk2
│ ├── checksums.txt
│ ├── columns.txt
│ ├── count.txt
│ ├── id.bin
│ ├── id.mrk2
│ ├── minmax_brandId.idx
│ ├── minmax_shopId.idx
│ ├── partition.dat
│ ├── primary.idx
│ ├── saleDate.bin
│ ├── saleDate.mrk2
│ ├── saleMoney.bin
│ ├── saleMoney.mrk2
│ ├── shopId.bin
│ ├── shopId.mrk2
│ ├── vipId.bin
│ └── vipId.mrk2
├── 429-6001_3_3_0
│ ├── brandId.bin
│ ├── brandId.mrk2
│ ├── checksums.txt
│ ├── columns.txt
│ ├── count.txt
│ ├── id.bin
│ ├── id.mrk2
│ ├── minmax_brandId.idx
│ ├── minmax_shopId.idx
│ ├── partition.dat
│ ├── primary.idx
│ ├── saleDate.bin
│ ├── saleDate.mrk2
│ ├── saleMoney.bin
│ ├── saleMoney.mrk2
│ ├── shopId.bin
│ ├── shopId.mrk2
│ ├── vipId.bin
│ └── vipId.mrk2
├── 429-6002_2_2_0
│ ├── brandId.bin
│ ├── brandId.mrk2
│ ├── checksums.txt
│ ├── columns.txt
│ ├── count.txt
│ ├── id.bin
│ ├── id.mrk2
│ ├── minmax_brandId.idx
│ ├── minmax_shopId.idx
│ ├── partition.dat
│ ├── primary.idx
│ ├── saleDate.bin
│ ├── saleDate.mrk2
│ ├── saleMoney.bin
│ ├── saleMoney.mrk2
│ ├── shopId.bin
│ ├── shopId.mrk2
│ ├── vipId.bin
│ └── vipId.mrk2
├── detached
└── format_version.txt
分区目录可以总结为:
查看物理结构:
table_name
|---partition 1
| |--checksums.txt
| |--columns.txt
| |--count.txt
| |--primary.idx
| |--[column].bin
| |--[column].mrk
| |--[column].mrk2
(以上为基础文件)
| |--partition.dat
| |--minmax_[column].idx
(以上为使用了分区键的时候生成的文件)
| |--skp_idx_[column].idx
| |--skp_idx_[column].mrk
(以上为使用二级索引时候才会生成的文件)
|---partition_2
|
|---partition_n
解释:
1.partition 分区目录
partition_n目录下的各类数据文件都是以分区形式被组织存放的,属于相同分区的数据最终会被合并到同一个分区目录内。
2.checksums.txt:校验文件,使用二进制存储,保存了各类文件的size大小和size的哈希值,用于快速校验文件的完整性和正确性。
3.columns.txt:列信息文件,使用文本文件存储,用于保存分区下的列字段信息。
4.count.txt:计数文件,文本文件存储,用于记录当前数据分区目录下数据的总行数。
5.primary.idx:以及索引文件,使用二进制格式存储。用于存放稀疏索引,一张MergeTree表只能声明一次一级索引
(通过order by或者primary key)。借助稀疏索引在数据查询的时候能够排除主键范围之外的数据文件,从而减少数据扫描范围,加速查询速度。
6.[column].bin:数据文件,使用压缩格式存储,默认使用LZ4压缩格式,用于存储某一列的数据。由于MergeTree采用列式存储,每个列字段都拥有独立的bin数据文件,并以列字段命名。
7.[column].mrk列字段标记,使用二进制格式存储。标记文件中保存了bin文件中数据的偏移量信息,标记文件与稀疏文件对齐,又与bin文件一一对应,所以MergeTree通过标记文件建立了primary.idx稀疏索引与bin数据文件的隐射关系。
首先通过primary.idx找到对应数据的偏移量信息(.mrk),再通过偏移量直接从bin文件中读取数据。由于.mrk标记文件与.bin文件一一对应,所以MergeTree中的每个列字段都会拥有与其对应的.mrk文件。
8.[column].mrk2 如使用了自适应大小的索引间隔,则标记文件会以.mrk2命名。工作原理和作用和.mrk标记文件相同。
9.partition.dat和minmax_[column].idx:
若使用了分区键则会额外生成partition.dat和minmax索引文件,均使用二进制格式存储。partition.dat用于保存当前分区下
分区表达式最终生成值,minmax索引文件用于记录当前分区字段对应原始数据的最小值和最大值。
在分区索引作用下,进行数据查询时候能够快速跳过不必要的数据分区目录,从而减少最终需要扫描的数据范围。
10.skp_idx_[column].idx和skp_idx_[column].mrk:
若在建表语句中声明了二级索引则会额外生成相应的二级索引与标记文件,他们同样用二进制存储。
二级索引在clickhouse中又称之为跳数索引,目前拥有minmax,set,ngrambf_v1和tokenbf_v1四种类型。
这些索引的目标和一级稀疏索引相同,为了进一步减少所需要扫描的数据范围,以加速整个查询过程。
元数据也显示3个分区
b64d9704419c :) select * from system.parts where table='tb_test_MergeTree_partitions';
SELECT *
FROM system.parts
WHERE table = 'tb_test_MergeTree_partitions'
┌─partition──┬─name───────────┬─part_type─┬─active─┬─marks─┬─rows─┬─bytes_on_disk─┬─data_compressed_bytes─┬─data_uncompressed_bytes─┬─marks_bytes─┬───modification_time─┬─────────remove_time─┬─refcount─┬───min_date─┬───max_date─┬────────────min_time─┬────────────max_time─┬─partition_id─┬─min_block_number─┬─max_block_number─┬─level─┬─data_version─┬─primary_key_bytes_in_memory─┬─primary_key_bytes_in_memory_allocated─┬─is_frozen─┬─database────┬─table────────────────────────┬─engine────┬─disk_name─┬─path──────────────────────────────────────────────────────────────────────────────┬─hash_of_all_files────────────────┬─hash_of_uncompressed_files───────┬─uncompressed_hash_of_compressed_files─┐
│ (429,6001) │ 429-6001_1_1_0 │ Wide │ 1 │ 2 │ 1 │ 515 │ 186 │ 30 │ 288 │ 2020-11-10 12:02:17 │ 0000-00-00 00:00:00 │ 1 │ 0000-00-00 │ 0000-00-00 │ 0000-00-00 00:00:00 │ 0000-00-00 00:00:00 │ 429-6001 │ 1 │ 1 │ 0 │ 1 │ 16 │ 8192 │ 0 │ liucf_ch_db │ tb_test_MergeTree_partitions │ MergeTree │ default │ /var/lib/clickhouse/data/liucf_ch_db/tb_test_MergeTree_partitions/429-6001_1_1_0/ │ 5ae63955e604e81bc6953807bb8a0d90 │ a056aa3b81f706269477195ad7bec7f5 │ ed4f2b96eecf6163ce254fe3a95ee387 │
│ (429,6001) │ 429-6001_3_3_0 │ Wide │ 1 │ 2 │ 1 │ 515 │ 186 │ 30 │ 288 │ 2020-11-10 12:02:17 │ 0000-00-00 00:00:00 │ 1 │ 0000-00-00 │ 0000-00-00 │ 0000-00-00 00:00:00 │ 0000-00-00 00:00:00 │ 429-6001 │ 3 │ 3 │ 0 │ 3 │ 16 │ 8192 │ 0 │ liucf_ch_db │ tb_test_MergeTree_partitions │ MergeTree │ default │ /var/lib/clickhouse/data/liucf_ch_db/tb_test_MergeTree_partitions/429-6001_3_3_0/ │ 32f9affed43b1e1923f39eb504c14e5d │ a056aa3b81f706269477195ad7bec7f5 │ fd82447c9310b82ae3fc16fc83ad08e4 │
│ (429,6002) │ 429-6002_2_2_0 │ Wide │ 1 │ 2 │ 1 │ 515 │ 186 │ 30 │ 288 │ 2020-11-10 12:02:17 │ 0000-00-00 00:00:00 │ 1 │ 0000-00-00 │ 0000-00-00 │ 0000-00-00 00:00:00 │ 0000-00-00 00:00:00 │ 429-6002 │ 2 │ 2 │ 0 │ 2 │ 16 │ 8192 │ 0 │ liucf_ch_db │ tb_test_MergeTree_partitions │ MergeTree │ default │ /var/lib/clickhouse/data/liucf_ch_db/tb_test_MergeTree_partitions/429-6002_2_2_0/ │ 00821628c0d605b2362e419b1b9e1416 │ a1907fcfa6f06f478d357267ced4f5e7 │ d2683ef0e82d3a8805ca211845e3ac85 │
└────────────┴────────────────┴───────────┴────────┴───────┴──────┴───────────────┴───────────────────────┴─────────────────────────┴─────────────┴─────────────────────┴─────────────────────┴──────────┴────────────┴────────────┴─────────────────────┴─────────────────────┴──────────────┴──────────────────┴──────────────────┴───────┴──────────────┴─────────────────────────────┴───────────────────────────────────────┴───────────┴─────────────┴──────────────────────────────┴───────────┴───────────┴───────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────┴──────────────────────────────────┴───────────────────────────────────────┘
按理说429-6001_1_1_0和429-6001_3_3_0是同一个分区,为什么会在两个分区里呢?是因为,同一批次插入的数据会重新按照partition by 分区写入不会理会之前的批次写入的同样分区的数据,写入后clickhouse会不定时的自动通过内部机制进行合并,合并的过程是会重新生成一个分区,然后把历史分区标志成is not active 状态(也就是active=0),然后再过段时间吧active=0的分区目录删除掉待验证
ClickHouse 会定期的对插入的数据片段进行合并,大约是在插入后15分钟左右。此外,你也可以使用 OPTIMIZE 语句发起一个计划外的合并
为了演示自动合并过程这里强制让clickhouse合并一次分区,
optimize table tb_test_MergeTree_partitions
注意也可以对单个分区进行合并比如:
OPTIMIZE TABLE visits PARTITION 429-6001;
执行
b64d9704419c :) optimize table tb_test_MergeTree_partitions
OPTIMIZE TABLE tb_test_MergeTree_partitions
Ok.
0 rows in set. Elapsed: 0.003 sec.
b64d9704419c :) select * from tb_test_MergeTree_partitions
SELECT *
FROM tb_test_MergeTree_partitions
┌────id─┬─vipId─┬─brandId─┬─shopId─┬───saleDate─┬─saleMoney─┐
│ 10002 │ 8002 │ 429 │ 6002 │ 2020-10-02 │ 300.5 │
└───────┴───────┴─────────┴────────┴────────────┴───────────┘
┌────id─┬─vipId─┬─brandId─┬─shopId─┬───saleDate─┬─saleMoney─┐
│ 10001 │ 8001 │ 429 │ 6001 │ 2020-10-01 │ 200.5 │
│ 10003 │ 8001 │ 429 │ 6001 │ 2020-10-02 │ 100.5 │
└───────┴───────┴─────────┴────────┴────────────┴───────────┘
3 rows in set. Elapsed: 0.002 sec.
b64d9704419c :)
查看元数据确实是 429-6001_1_1_0 和 429-6001_3_3_0合并成了429-6001_1_3_1 同时把429-6001_1_1_0 和 429-6001_1_3_1的active设置成0 ,429-6002_2_2_0不变
b64d9704419c :) select * from system.parts where table='tb_test_MergeTree_partitions';
SELECT *
FROM system.parts
WHERE table = 'tb_