在MergeTree表引擎中,数据是以分区目录的形式进行组织的,每个分区独立分开存储,这样子在数据查询时候可以跳过无用的数据分区,最小化扫描的数据文件,从而达到加快查询的效果。本文将从分区的规则,底层目录的格式以及分区的合并规则等方面详细讲解数据分区目录具体是如何运作的。
MergeTree数据表的分区规则由分区 ID 决定,而具体到每个分区对应的 ID 则是由分区键的取值决定的。分区键支持使用任何一个或一组字段表达式声明,其业务语义可以是年、月、日或者组织单位等任何一种规则。针对取值数据的类型不同,分区 ID 的生成逻辑目前拥有四种规则:
对于MergeTree来说,最核心的特点是其分区目录的合并动作,从分区目录的命名中便可解读出它的合并逻辑,一个完整的分区目录的命名公式如下所示:PartitionID_MinBlockNum_MaxBlockNum_Level
MergeTree 的分区目录和其它传统意义上数据库有所不同,主要表现在以下两个方面:
分区合并是clickhouse异步对数据合并并进行压缩,主要为了节省空间,属于同一个分区的多个目录,在合并之后会生成一个全新的目录,目录中的索引和数据文件也会相应地进行合并。而新目录的名称的生成方式遵循如下规则:
我们通过一个实例来详细看一下分区合并,假设我们之前的有一个partition_v5
的表,按照日期字段格式分区(Partition by toYYYYMM(EventTime)
:
T0时刻插入数据:
INSERT INTO partition_v5 VALUES (1, '张三', '2020-05-01');
INSERT INTO partition_v5 VALUES (1, '李四', '2020-05-02');
INSERT INTO partition_v5 VALUES (1, '王五', '2020-06-01');
T2时刻插入数据:
INSERT INTO partition_v5 VALUES (1, '张三', '2020-05-01');
INSERT INTO partition_v5 VALUES (1, '李四', '2020-05-02');
INSERT INTO partition_v5 VALUES (1, '王五', '2020-06-01');
如果再写入数据的话,那么 MergeTree 依旧会发生合并,然后重复和上面的一样的动作。我们上面显示的是目录合并之后的结果,至于旧的分区目录、也就是合并之前的目录会依旧保留一段时间,但已不再是激活状态(active = 0),在数据查询的时候会被过滤掉。然后 ClickHouse 有一个后台任务会定时扫描(默认 8 分钟),负责将 active = 0 的目录从物理磁盘上删除。
最后,我们用一张完整的示例图作为总结,描述MergeTree分区目录从创建,合并到删除的整体过程:
SELECT
partition,
name,
active
FROM system.parts
WHERE table = 'xx' and database ='xx';
系统表属性解析如下:
但是有些特殊场景下,用户希望立刻删除老的数据目录,这种需求可以在创建MergeTree表的时候通过Settings属性来设置,old_parts_lifetime 这个属性的含义是多久删除老的分区数据目录。单位是秒
ALTER TABLE table_name DETACH PARTITION|PART partition_expr
将指定分区的所有数据移动到detached
目录中,服务器忘记了分离的数据分区,就好像它不存在一样。在进行ATTACH查询之前,服务器不会知道此数据。
ALTER TABLE mt DETACH PARTITION '2020-11-21';
ALTER TABLE mt DETACH PART 'all_2_2_0';
执行查询后,你可以对detached
目录中的数据做任何你想做的事情,从文件系统中删除它,或者直接离开它。它将数据移动到detached
所有副本上的目录。请注意,只能在领导者副本上执行此查询,要确定副本是否是领导者,请对system.replicas表执行SELECT
查询。
ALTER TABLE table_name DROP PARTITION|PART partition_expr
从表中删除指定的分区。此查询将分区标记为非活动并完全删除数据,大约在 10 分钟内。
ALTER TABLE table_name DROP DETACHED PARTITION|PART partition_expr
删除指定分区的指定数据块或所有数据块detached
。
ALTER TABLE table_name ATTACH PARTITION|PART partition_expr
将数据从detached
目录添加到表中。可以为整个分区或单独的数据块添加数据。例子:
ALTER TABLE visits ATTACH PARTITION 201901;
ALTER TABLE visits ATTACH PART 201901_2_2_0;
副本发起者检查目录中是否有数据detached
。如果数据存在,则查询检查其完整性。如果一切正确,则查询将数据添加到表中。如果接收到附加命令的非发起者副本在其自己的detached
文件夹中找到具有正确校验和的数据块,它会附加数据而不从其他副本中获取数据。如果没有具有正确校验和的零件,则从具有该零件的任何副本下载数据,可以将数据detached
放在一个副本上的目录中,并使用ALTER ... ATTACH
查询将其添加到所有副本上的表中。
ALTER TABLE table2 ATTACH PARTITION partition_expr FROM table1
此查询将数据分区从 复制table1
到table2
。请注意,既不会从table1
也不会从中删除数据table2
。要使查询成功运行,必须满足以下条件:
ALTER TABLE table2 REPLACE PARTITION partition_expr FROM table1
此查询将数据分区从 复制table1
到table2
并替换 中的现有分区table2
。请注意,数据不会从table1
,要使查询成功运行,必须满足以下条件:
ALTER TABLE table_source MOVE PARTITION partition_expr TO TABLE table_dest
此查询将数据分区从 移动table_source
到,并从 中table_dest
删除数据table_source
,要使查询成功运行,必须满足以下条件:
ALTER TABLE table_name CLEAR COLUMN column_name IN PARTITION partition_expr
重置分区中指定列中的所有值。如果DEFAULT
在创建表时确定了该子句,则此查询将列值设置为指定的默认值。
此查询创建指定分区的本地备份。如果PARTITION
省略该子句,则查询会立即创建所有分区的备份。
ALTER TABLE table_name FREEZE [PARTITION partition_expr] [WITH NAME 'backup_name']
从磁盘中删除freezed
具有指定名称的分区。如果PARTITION
省略该子句,则查询会立即删除所有分区的备份。
ALTER TABLE 'table_name' UNFREEZE [PARTITION 'part_expr'] WITH NAME 'backup_name'
该查询的工作方式类似于CLEAR COLUMN
,但它重置索引而不是列数据。
ALTER TABLE table_name CLEAR INDEX index_name IN PARTITION partition_expr
ALTER TABLE table_name FETCH PARTITION|PART partition_expr FROM 'path-in-zookeeper'
从另一台服务器下载分区,此查询仅适用于复制的表。查询执行以下操作:
detached
目录下table_name
。使用ATTACH PARTITION|PART查询将数据添加到表中。获取分区
ALTER TABLE users FETCH PARTITION 201902 FROM '/clickhouse/tables/01-01/visits';
ALTER TABLE users ATTACH PARTITION 201902;
获取数据块
ALTER TABLE users FETCH PART 201901_2_2_0 FROM '/clickhouse/tables/01-01/visits';
ALTER TABLE users ATTACH PART 201901_2_2_0;
注意:
ALTER ... FETCH PARTITION|PART
复制。它仅将部件或分区detached
放置到本地服务器上的目录中。ALTER TABLE ... ATTACH
复制。它将数据添加到所有副本。数据从detached
目录添加到其中一个副本,并从相邻副本添加到其他副本。在下载之前,系统会检查分区是否存在以及表结构是否匹配。从健康的副本中自动选择最合适的副本。虽然调用了查询ALTER TABLE
,但它不会更改表结构,也不会立即更改表中可用的数据。
将分区或数据块移动到另一个卷或磁盘以用于MergeTree
-engine 表。
ALTER TABLE table_name MOVE PARTITION|PART partition_expr TO DISK|VOLUME 'disk_name'
ALTER TABLE t MOVE
查询:
ALTER TABLE t MOVE
查询或后台数据合并的结果移动的情况下,可以返回错误。在这种情况下,用户不应执行任何其他操作。操作与指定过滤表达式匹配的指定分区中的数据。
ALTER TABLE [db.]table UPDATE column1 = expr1 [, ...] [IN PARTITION partition_id] WHERE filter_expr
删除与指定过滤表达式匹配的指定分区中的数据。
ALTER TABLE [db.]table DELETE [IN PARTITION partition_id] WHERE filter_expr