自定义分区及底层存储合并机制

1.自定义分区键

  1. 分区是在建表时使用PARTITION BY expr子句指定
  2. 分区键可以是表列中的任何表达式
    例如,按月指定分区:PARTITION BY toYYYYMM(date_column)。
    使用元组指定分区:PARTITION BY (toMonday(StartDate),EventType)
  3. 在将新数据插入表中时,每个分区的数据存储为单独的数据片段(每个数据片段的数 据是按主键排序的),在插入后的10-15分钟内,同一个分区的数据片段将合并为一个整 体的数据片段

2.分区目录的命名规则

根据分区表达式的数据类型,分区的命名规则是存在差异的。

  1. 不指定分区:分区名称为all
  2. 数值数据类型:分区名称为数值。
  3. 日期数据类型:将日期转换为数字作为分区名称。
  4. 字符串数据类型:将日期转换为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.分区目录的合并过程

  1. active列为数据片段的状态。1表示激活状态,0表示非激活状态。当源数据片段合并为较大的片段之后,这些源的数据片段就变为了非激活状态。损坏的数据片段也是非激活状态
  2. 同一分区有多个独立的数据片段,这表明这些片段尚未合并。
    ClickHouse会在插入后大约15分钟后合并数据片段,也可以使用OPTIMIZE语句执行计划外的合并:OPTIMIZE TABLE mergeTableDemo PARTITION 202004
  3. 非激活的片段(active=0片段)将在合并后约10分钟被删除。
  4. 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.分区案例

  1. 不指定分区
    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');
    
  2. 分区是数值
    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');
    
  3. 分区是日期
    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');
    
  4. 分区是字符串
    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');
    
  5. 查看分区信息,可以通过如下方式:
    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 :)
    

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值