1.自定义分区键
- 分区是在建表时使用PARTITION BY expr子句指定
- 分区键可以是表列中的任何表达式
例如,按月指定分区:PARTITION BY toYYYYMM(date_column)。
使用元组指定分区:PARTITION BY (toMonday(StartDate),EventType)- 在将新数据插入表中时,每个分区的数据存储为单独的数据片段(每个数据片段的数 据是按主键排序的),在插入后的10-15分钟内,同一个分区的数据片段将合并为一个整 体的数据片段
2.分区目录的命名规则
根据分区表达式的数据类型,分区的命名规则是存在差异的。
- 不指定分区:分区名称为all
- 数值数据类型:分区名称为数值。
- 日期数据类型:将日期转换为数字作为分区名称。
- 字符串数据类型:将日期转换为hash作为分区名称。
系统表:
xxxxx :) SELECT partition,name,table,active FROM system.parts WHERE table like '%demo%'; SELECT partition, name, table, active FROM system.parts WHERE table LIKE '%demo%' ┌─partition─┬─name─────────┬─table─────────────┬─active─┐ │ 201403 │ 201403_1_1_0 │ TabSeparated_demo │ 1 │ └───────────┴──────────────┴───────────────────┴────────┘ 1 rows in set. Elapsed: 0.009 sec. xxxxx :)
3.分区目录的合并过程
在将新数据插入表中时,每个分区的数据按照目录存储为单独的数据片段,目录名为数据片段名称,这个和System.parts表的name字段一致。
在插入后的10-15分钟内,同一个分区的数据片段将合并为一个整体的数据片段。
数据片段名称包含了4部分的信息,下面以数据片段20200421_1_2_1为例进行拆解:
- 20200421是分区名称。
- 1是数据块的最小编号。
- 2 是数据块的最大编号。
- 1 是块级别,即该块在MergeTree中的深度。
4.分区目录的合并过程
- active列为数据片段的状态。1表示激活状态,0表示非激活状态。当源数据片段合并为较大的片段之后,这些源的数据片段就变为了非激活状态。损坏的数据片段也是非激活状态
- 同一分区有多个独立的数据片段,这表明这些片段尚未合并。
ClickHouse会在插入后大约15分钟后合并数据片段,也可以使用OPTIMIZE语句执行计划外的合并:OPTIMIZE TABLE mergeTableDemo PARTITION 202004- 非激活的片段(active=0片段)将在合并后约10分钟被删除。
- detached目录包含使用DETACHED语句从表分离的数据片段。损坏的数据片段也将移至该目录,而不是被删除。ClickHouse不会使用detached目录中的数据片段。此目录中的数据可以随时添加、删除或修改,ClickHouse只能在运行ATTACH语句时才会感知该目录
5.分区表达式指定
alter语句、optimize语句通常需要指定分区的表达式,分区表达式的值为system.parts的partition字段, 而不是分区的名称,这里需要注意。
因为字符串和日期类型的分区,分区名称和分区表达式的值是不一样的。
例如:日期类型的分区:
分区表达式的值是2020-04-21,分区名称为20200421。
上面的值可以通过类似如下的方式查询到:
select p.`partition` as `partition`, p.name as name, p.`table` as `table`, p.active as active from `system`.parts p where p.`table` = 'test_partition_date'
执行optimize操作:
optimize table test_partition partition '2020-04-21'。
不能写成:
optimize table test_partition partition '20200421。
6.分区案例
- 不指定分区
drop table test_partition_non; create table test_partition_non(name String, timestamp DateTime) ENGINE=MergeTree() order by name; insert into test_partition_non values ('nanjing', '2020-04-21 12:23:33');
- 分区是数值
drop table test_partition_numeric; create table test_partition_numeric(id UInt64, timestamp DateTime) ENGINE=MergeTree() order by id partition by id; insert into test_partition_numeric values (556, '2020-04-21 12:23:33');
- 分区是日期
drop table test_partition_date; create table test_partition_date(date Date, timestamp DateTime) ENGINE=MergeTree() order by date partition by date; insert into test_partition_date values ('2020-04-21', '2020-04-21 12:23:33');
- 分区是字符串
drop table test_partition_string; create table test_partition_string(name String, timestamp DateTime) ENGINE=MergeTree() order by name partition by name; insert into test_partition_string values ('hangzhou', '2020-04-21 12:23:33');
- 查看分区信息,可以通过如下方式:
SELECT partition,name,table,active FROM system.parts WHERE table like ‘test_partition_%’; xxxxx :) SELECT partition, name, table, active FROM system.parts WHERE table like 'test_partition_%'; SELECT partition, name, table, active FROM system.parts WHERE table LIKE 'test_partition_%' ┌─partition─┬─name──────┬─table──────────────────┬─active─┐ │ tuple() │ all_1_1_0 │ test_partition_date │ 1 │ │ tuple() │ all_1_1_0 │ test_partition_non │ 1 │ │ 556 │ 556_1_1_0 │ test_partition_numeric │ 1 │ └───────────┴───────────┴────────────────────────┴────────┘ 3 rows in set. Elapsed: 0.010 sec. xxxxx :)