MergeTree系列表引擎之TTL

1.TTL

​ TTL即time To Live,数据的存活时间。

​ MergeTree中,可以为某个列字段,或者整张表设置TTL。当时间到达时,如果是列字段级别为TTL,则会删除这一列数据;如果是表级别为TTL,则会删除整张表的数据;如果同时设置了列级别和表级别的TTL,会以先到时间的为准删除数据。

​ 无论是列或者表级别的TTL,都依靠DateTime或Date类型字段,通过对这个时间字段的INTERVAL操作,来确定TTL过期时间:

示例:

​ TTL time_column + interval 3 DAY

​ 表示数据存活的时间为time_column 时间的3天之后。

​ TTL time_column + interval 1 MONTH

​ 表示数据存活的时间为time_column 时间的1月之后。

​ INTERVAL支持的操作:second,minute,hour,day,week,month,quarter,year。

1.1 列级别的TTL

若要设置列级别的TTL,则需要在定义表字段的时候,为他们声明TTL表达式,主键字段不能被声明TTL。

示例:

CREATE TABLE t_column_ttl
(
    id UInt64 COMMENT 'Primary key',
    create_time Datetime,
    product_desc String TTL create_time + toIntervalSecond(10),
    product_type UInt8 TTL create_time + toIntervalSecond(10)
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(create_time)
ORDER BY id

insert into table t_column_ttl values(1,now(),'Huawei',1),(2,now()+interval 1 minute,'Apple',2);

select * from t_column_ttl;

┌─id─┬─────────create_time─┬─product_desc─┬─product_type─┐
│  12021-03-11 09:12:04 │ Huawei       │            1 │
│  22021-03-11 09:13:04 │ Apple        │            2 │
└────┴─────────────────────┴──────────────┴──────────────┘

select sleep(10);
select * from t_column_ttl;
┌─id─┬─────────create_time─┬─product_desc─┬─product_type─┐
│  12021-03-11 09:12:04 │              │            0 │
│  22021-03-11 09:13:04 │ Apple        │            2 │
└────┴─────────────────────┴──────────────┴──────────────┘


optimize table t_column_ttl final;
select * from t_column_ttl;
┌─id─┬─────────create_time─┬─product_desc─┬─product_type─┐
│  12021-03-11 09:12:04 │              │            0 │
│  22021-03-11 09:13:04 │              │            0 │
└────┴─────────────────────┴──────────────┴──────────────┘

# 执行optimize命令会强制触发TTL清理,若再次查询可以看到满足TTL条件之后,定义了TTL操作的字段列会被还原为数据类型的默认值。

# 修改列字段的TTL或者修改已有字段的TTL:
alter table t_column_ttl MODIFY COLUMN product_desc String  TTL create_time + INTERVAL  2 DAY;
# 添加字段的TTL:
alter table t_column_ttl add column product_name String comment '产品名称' ttl create_time + interval 3 month;

# 查看TTL的信息:
desc t_column_ttl\G

Row 1:
──────
name:               id
type:               UInt64
default_type:       
default_expression: 
comment:            Primary key
codec_expression:   
ttl_expression:     

Row 2:
──────
name:               create_time
type:               DateTime
default_type:       
default_expression: 
comment:            
codec_expression:   
ttl_expression:     

Row 3:
──────
name:               product_desc
type:               String
default_type:       
default_expression: 
comment:            
codec_expression:   
ttl_expression:     create_time + toIntervalSecond(10)

Row 4:
──────
name:               product_type
type:               UInt8
default_type:       
default_expression: 
comment:            
codec_expression:   
ttl_expression:     create_time + toIntervalSecond(10)

1.2 表级别的TTL

可以在MergeTree的表参数中增加TTL表达式 为整张表设置TTL。

# 表的定义:
CREATE TABLE t_table_ttl
(
    `id` UInt64 COMMENT '主键',
    `create_time` Datetime COMMENT '创建时间',
    `product_desc` String COMMENT '产品描述' ,
    `product_type` UInt8 COMMENT '产品序号'
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(create_time)
ORDER BY create_time
TTL create_time + toIntervalSecond(10)

insert into table t_table_ttl values(1,now(),'Huawei',1),(2,now()+interval 1 minute,'Apple',2);

select *from t_table_ttl;
┌─id─┬─────────create_time─┬─product_desc─┬─product_type─┐
│  12021-03-11 09:29:30 │ Huawei       │            1 │
│  22021-03-11 09:30:30 │ Apple        │            2 │
└────┴─────────────────────┴──────────────┴──────────────┘

optimize table t_table_ttl final;

select *from t_table_ttl;

Ok.

0 rows in set. Elapsed: 0.009 sec. 

表级别的TTL修改:
alter table t_table_ttl modify ttl create_time + interval 2 month;
alter table t_table_ttl modify ttl create_time + tointervalMonth(2);


查看信息:
SELECT 
    database,
    name,
    engine,
    data_paths,
    metadata_path,
    metadata_modification_time,
    partition_key,
    sorting_key
FROM system.tables
WHERE name = 't_table_ttl'

Row 1:
──────
database:                   default
name:                       t_table_ttl
engine:                     MergeTree
data_paths:                 ['/var/lib/clickhouse/data/default/t_table_ttl/']
metadata_path:              /var/lib/clickhouse/metadata/default/t_table_ttl.sql
metadata_modification_time: 2021-03-11 09:40:05
partition_key:              toYYYYMM(create_time)
sorting_key:                create_time


# 查看表的结构:
DESCRIBE TABLE t_table_ttl

Row 1:
──────
name:               id
type:               UInt64
default_type:       
default_expression: 
comment:            主键
codec_expression:   
ttl_expression:     

Row 2:
──────
name:               create_time
type:               DateTime
default_type:       
default_expression: 
comment:            创建时间
codec_expression:   
ttl_expression:     

Row 3:
──────
name:               product_desc
type:               String
default_type:       
default_expression: 
comment:            产品描述
codec_expression:   
ttl_expression:     create_time + toIntervalMinute(10)

Row 4:
──────
name:               product_type
type:               UInt8
default_type:       
default_expression: 
comment:            产品序号
codec_expression:   
ttl_expression:   

注意:列级别或者表级别的TTL 目前暂不支持取消操作。
1.3 TTL的运行机理
若一张MergeTree表被设置为TTL 则在写入数据时候会以数据分区为单位,在每个分区目录内生成一个ttl.txt的文件。

写入数据:

CREATE TABLE default.t_table_ttl
(
    `id` UInt64 COMMENT '主键',
    `create_time` DateTime COMMENT '创建时间',
    `product_desc` String COMMENT '产品描述',
    `product_type` UInt8 COMMENT '产品序号'
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(create_time)
ORDER BY create_time
TTL create_time + toIntervalMinute(10)
SETTINGS index_granularity = 8192;

insert into t_table_ttl(id,create_time,product_desc,product_type)values(10,now(),'Huawei',1),(20,now()+ interval 10 minute,'Apple',2);

┌─id─┬─────────create_time─┬─product_desc─┬─product_type─┐
│ 102021-03-11 10:04:21 │ Huawei       │            1 │
│ 202021-03-11 10:14:21 │ Apple        │            2 │
└────┴─────────────────────┴──────────────┴──────────────┘
ll /var/lib/clickhouse/data/default/t_table_ttl/
total 4
drwxr-x--- 2 clickhouse clickhouse 322 Mar 11 09:51 202103_1_1_0
drwxr-x--- 2 clickhouse clickhouse   6 Mar 11 09:51 detached
-rw-r----- 1 clickhouse clickhouse   1 Mar 11 09:51 format_version.txt

 ll /var/lib/clickhouse/data/default/t_table_ttl/202103_1_1_0/
total 60
-rw-r----- 1 clickhouse clickhouse 464 Mar 11 09:51 checksums.txt
-rw-r----- 1 clickhouse clickhouse 115 Mar 11 09:51 columns.txt
-rw-r----- 1 clickhouse clickhouse   1 Mar 11 09:51 count.txt
-rw-r----- 1 clickhouse clickhouse  34 Mar 11 09:51 create_time.bin
-rw-r----- 1 clickhouse clickhouse  48 Mar 11 09:51 create_time.mrk2
-rw-r----- 1 clickhouse clickhouse  39 Mar 11 09:51 id.bin
-rw-r----- 1 clickhouse clickhouse  48 Mar 11 09:51 id.mrk2
-rw-r----- 1 clickhouse clickhouse   8 Mar 11 09:51 minmax_create_time.idx
-rw-r----- 1 clickhouse clickhouse   4 Mar 11 09:51 partition.dat
-rw-r----- 1 clickhouse clickhouse   8 Mar 11 09:51 primary.idx
-rw-r----- 1 clickhouse clickhouse  39 Mar 11 09:51 product_desc.bin
-rw-r----- 1 clickhouse clickhouse  48 Mar 11 09:51 product_desc.mrk2
-rw-r----- 1 clickhouse clickhouse  28 Mar 11 09:51 product_type.bin
-rw-r----- 1 clickhouse clickhouse  48 Mar 11 09:51 product_type.mrk2
-rw-r----- 1 clickhouse clickhouse  67 Mar 11 09:51 ttl.txt

cat /var/lib/clickhouse/data/default/t_table_ttl/202103_1_1_0/ttl.txt 
ttl format version: 1
{
    
    "table":{
    
    "min":1615428861,"max":1615429461}}

可以看到MergeTree是通过一串JSON配置保存了TTL的相关信息。
columns 用于保存列级别的TTL信息
tables 用于保存表级别的TTL信息
min和max则保存了当前数据分区内TTL指定的日期字段的最小值和最大值分别与INTERVAL表达式计算后的时间戳。

查找JSON中格林威治时间表对应的国内时间
(ttl_max - max(create_time) expire_max
ttl_min - min(create_time) expire_min)

select toDateTime('1615428861') ttl_min,toDateTime('1615429461') ttl_max,ttl_min - min(create_time) expire_min,ttl_max - max(create_time) expire_max from t_table_ttl;

┌─────────────ttl_min─┬─────────────ttl_max─┬─expire_min─┬─expire_max─┐
│ 2021-03-11 10:14:212021-03-11 10:24:21600600 │
└─────────────────────┴─────────────────────┴────────────┴────────────┘

可以看ttl.txt 记录的极值区间恰好等于当前数据分区内create_time的最大值和最小值加10分钟(600S ),和TTL的表达式(TTL create_time + toIntervalMinute(10))的预期相符合。

通过TTL的信息记录方式 可以推断大体的处理逻辑:

1.MergeTree 是以分区目录为单位,通过ttl.txt 记录过期时间,并以此作为判断标准。

2.每当写入一批数据时候,都会基于interval 表达式的计算结果为这个分区生成ttl.txt 文件

3.只有在MergeTree合并分区才会触发TTL过期数据的逻辑

4.在删除分区的时候,选择使用了贪婪算法,算法规则即尽可能找到会最早过期,同时时间最早的分区。

5.若一个分区内某一列因为TTL到期则全部删除,在合并之后生成的新分区目录中将不会包含这个列字段的数据文件(.bin 和.mrk)

注意:

1.TTL默认的合并频率有MergeTree的参数merge_with_ttl_timeout 控制,默认周期为86400秒。它专门维护一个专有的TTL任务队列。有别于MergeTree的常规合并任务,若这个值设置的过小则可能会带来性能损耗。

此设置意味着仅在一个分区上或发生后台合并时,每24小时执行一次TTL删除。因此,在最坏的情况下,ClickHouse现在最多每24小时删除一个与TTL delete表达式匹配的分区。

此行为可能并不理想,因此,如果您希望TTL删除表达式更快地执行删除操作,则可以修改表的merge_with_ttl_timeout设置为一个小时。

alter table t_table_ttl  MODIFY SETTING merge_with_ttl_timeout = 3600;

2.除了触发TTL合并外,optimize 命令可以强制触发合并。

触发一个分区合并:optimize table t;

触发所有分区合并:       optimize table t final;

3.目前没有删除ttl的声明方法,但是提供了全局控制TTL合并任务的启动和关停方法:

system stop/start TTL MERGES

更多详情,请关注微信公众号
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45320660/article/details/114655052
TTL