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 = MergeTreePARTITION BY toYYYYMM(create_time)ORDER BY idinsert 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─┐│ 1 │ 2021-03-11 09:12:04 │ Huawei │ 1 ││ 2 │ 2021-03-11 09:13:04 │ Apple │ 2 │└────┴─────────────────────┴──────────────┴──────────────┘select sleep(10);select * from t_column_ttl;┌─id─┬─────────create_time─┬─product_desc─┬─product_type─┐│ 1 │ 2021-03-11 09:12:04 │ │ 0 ││ 2 │ 2021-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─┐│ 1 │ 2021-03-11 09:12:04 │ │ 0 ││ 2 │ 2021-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\GRow 1:──────name: idtype: UInt64default_type:default_expression:comment: Primary keycodec_expression:ttl_expression:Row 2:──────name: create_timetype: DateTimedefault_type:default_expression:comment:codec_expression:ttl_expression:Row 3:──────name: product_desctype: Stringdefault_type:default_expression:comment:codec_expression:ttl_expression: create_time + toIntervalSecond(10)Row 4:──────name: product_typetype: UInt8default_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 = MergeTreePARTITION BY toYYYYMM(create_time)ORDER BY create_timeTTL 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─┐│ 1 │ 2021-03-11 09:29:30 │ Huawei │ 1 ││ 2 │ 2021-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);查看信息:SELECTdatabase,name,engine,data_paths,metadata_path,metadata_modification_time,partition_key,sorting_keyFROM system.tablesWHERE name = 't_table_ttl'Row 1:──────database: defaultname: t_table_ttlengine: MergeTreedata_paths: ['/var/lib/clickhouse/data/default/t_table_ttl/']metadata_path: var/lib/clickhouse/metadata/default/t_table_ttl.sqlmetadata_modification_time: 2021-03-11 09:40:05partition_key: toYYYYMM(create_time)sorting_key: create_time# 查看表的结构:DESCRIBE TABLE t_table_ttlRow 1:──────name: idtype: UInt64default_type:default_expression:comment: 主键codec_expression:ttl_expression:Row 2:──────name: create_timetype: DateTimedefault_type:default_expression:comment: 创建时间codec_expression:ttl_expression:Row 3:──────name: product_desctype: Stringdefault_type:default_expression:comment: 产品描述codec_expression:ttl_expression: create_time + toIntervalMinute(10)Row 4:──────name: product_typetype: UInt8default_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 = MergeTreePARTITION BY toYYYYMM(create_time)ORDER BY create_timeTTL 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─┐│ 10 │ 2021-03-11 10:04:21 │ Huawei │ 1 ││ 20 │ 2021-03-11 10:14:21 │ Apple │ 2 │└────┴─────────────────────┴──────────────┴──────────────┘
ll var/lib/clickhouse/data/default/t_table_ttl/total 4drwxr-x--- 2 clickhouse clickhouse 322 Mar 11 09:51 202103_1_1_0drwxr-x--- 2 clickhouse clickhouse 6 Mar 11 09:51 detached-rw-r----- 1 clickhouse clickhouse 1 Mar 11 09:51 format_version.txtll 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.txtcat var/lib/clickhouse/data/default/t_table_ttl/202103_1_1_0/ttl.txtttl 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_maxttl_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:21 │ 2021-03-11 10:24:21 │ 600 │ 600 │└─────────────────────┴─────────────────────┴────────────┴────────────┘
可以看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




