Clickhouse TTL的那些事
TTL简介
ClickHouse原生支持数据生命周期(TTL)管理的功能
TTL即Time To Live,表示数据的存活时间。在MergeTree中,可以为某个列字段或者整张表设置TTL。当时间达到时,若列字段级别的TTL则会删除这一列的数据;若表级别的TTL则会删除整张表的数据;若同时设置了列级别的和表级别的TTL则以先到期的为准。
无论列级别还是表级别的TTL,都需要依托某个Datetime或者date类型的字段,通过对这个时间字段的INTERVAL操作来表述TTL的过期时间.
示例:
TTL time_column
TTL time_column + interval
要定义interval, 需要使用 时间间隔 操作符。
TTL date_time + INTERVAL 1 MONTH
TTL date_time + INTERVAL 15 HOUR
列TTL
当列中的值过期时, ClickHouse会将它们替换成该列数据类型的默认值。如果数据片段中列的所有值均已过期,则ClickHouse 会从文件系统中的数据片段中删除此列。
TTL子句不能被用于主键字段。
示例:
创建表时指定 TTL
CREATE TABLE example_table
(
d DateTime,
a Int TTL d + INTERVAL 1 MONTH,
b Int TTL d + INTERVAL 1 MONTH,
c String
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(d)
ORDER BY d;
为表中已存在的列字段添加 TTL:
ALTER TABLE example_table
MODIFY COLUMN
c String TTL d + INTERVAL 1 DAY;
修改列字段的 TTL:
ALTER TABLE example_table
MODIFY COLUMN
c String TTL d + INTERVAL 1 MONTH;
表TTL
表可以设置一个用于移除过期行的表达式,以及多个用于在磁盘或卷上自动转移数据片段的表达式。当表中的行过期时,ClickHouse 会删除所有对应的行。对于数据片段的转移特性,必须所有的行都满足转移条件。
TTL 规则的类型紧跟在每个 TTL 表达式后面,它会影响满足表达式时(到达指定时间时)应当执行的操作:
- DELETE - 删除过期的行(默认操作);
- TO DISK 'aaa' - 将数据片段移动到磁盘 aaa;
- TO VOLUME 'bbb' - 将数据片段移动到卷 bbb.
示例:
创建时指定 TTL
CREATE TABLE example_table
(
d DateTime,
a Int
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(d)
ORDER BY d
TTL d + INTERVAL 1 MONTH [DELETE],
d + INTERVAL 1 WEEK TO VOLUME 'aaa',
d + INTERVAL 2 WEEK TO DISK 'bbb';
修改表的 TTL:
ALTER TABLE example_table
MODIFY TTL d + INTERVAL 1 DAY;
删除数据
ClickHouse 在数据片段合并时会删除掉过期的数据。
当ClickHouse发现数据过期时, 它将会执行一个计划外的合并。要控制这类合并的频率, 可以设置 merge_with_ttl_timeout。如果该值被设置的太低, 它将引发大量计划外的合并,这可能会消耗大量资源。
如果在合并的过程中执行 SELECT 查询, 则可能会得到过期的数据。为了避免这种情况,可以在 SELECT 之前使用 OPTIMIZE 查询。
测试分析
首先准备一个已经做好冷热盘的clickhouse:
创建一个test ttl表,数据1分钟过期,超时时间1分钟。
CREATE TABLE test2
(
`d` DateTime,
`a` Int
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(d)
ORDER BY d
TTL d to volume 'default',
d + toIntervalMinute(1) TO VOLUME 'cold'
SETTINGS storage_policy = 'hot_and_cold';
更改merge_with_ttl_timeout:
ALTER TABLE test MODIFY SETTING merge_with_ttl_timeout = 60;
插入数据:
INSERT INTO TABLE test2 VALUES (now(),1),(now()-interval 1 minute,2),(now()-interval 2 minute,3),(now()-interval 3 minute,4);
这4条数据分别会在1分钟后、2分钟后、3分钟后过期。
现在查询test2的数据分布:
因为有1分钟前的数据写入,所以有部分数据直接被写在了冷盘。
等ttl到期后,再次查看test2表的数据分布:
可以看到数据全部被转移到了冷盘。
后记
此篇是对之前clickhouse做冷热分区的一个补充。希望大家一起学习,共同进步!