ClickHouse TTL for Columns and Tables

时间:2022-07-28
本文章向大家介绍ClickHouse TTL for Columns and Tables,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

导语

ClickHouse原生支持数据生命周期(TTL)管理的功能。

可以为整个表或每个单独的列设置TTL子句。表级TTL也可以指定在磁盘和分区之间自动移动数据的逻辑。 表达式的计算结果必须为DateDateTime数据类型。

示例:

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表

Table可以具有一个用于删除过期行的表达式,并可以具有多个用于在磁盘或分区之间自动移动数据块的表达式。当表格中的行到期时,ClickHouse会删除所有对应的行。对于数据块移动功能,数据块中的所有行都必须满足移动表达式条件。

TTL expr [DELETE|TO DISK 'aaa'|TO VOLUME 'bbb'], ...

TTL动作在TTL时间表达式之后给出,它决定在TTL表达式满足后(到达了当前的时间)将要执行的操作:

DELETE - 删除过期行 (默认动作);

TO DISK 'aaa' - 移动数据至磁盘A;

TO VOLUME 'bbb' - 移动数据至磁盘B.

示例:

创建一个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合并数据块时,将删除TTL过期的数据。

对于已过期的数据,ClickHouse将执行“计划外(off-schedule)”的合并。可以通过设置merge_with_ttl_timeout控制这种合并的频率。如果该值设定的太低,可能会执行许多计划外的合并,消耗大量资源。

如果在两个合并间隔之间执行SELECT查询,则可能会获取到过期的数据。为了避免这种情况,请在SELECT之前使用OPTIMIZE查询主动触发合并。

使用案例

某用户反馈TTL表不生效,设定的过期时间已经达到了,通过SELECT还是能查到过期的数据,通过上文可以看出用户可能是在两个合并间隔之间执行的查询,这样就可能会获取到过期的数据。为了进一步确认过期数据是否被清除以及计划外的合并有没有执行,可通过查询日志来进行诊断。

grep "expired TTL" /data/clickhouse/clickhouse-server/logs/clickhouse-server.log

上诉命令可以在ClickHouse日志文件中查到过期数据被处理的情况,如果有相关的日志信息则说明ClickHouse已经进行了off-schedule合并,再查询时就不会获取到过期的数据了。

测试分析

如果日志文件中查不到到ClickHouse对过期数据的处理日志就需要进一步测试该项功能是否work了,对此可在集群中创建一个TTL表进行测试。

CREATE TABLE ttl_table_test
(
    Ds DateTime,
    Id Int
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(Ds)
ORDER BY Ds
TTL Ds + INTERVAL 10 MINUTE;

ALTER TABLE ttl_table_test MODIFY SETTING merge_with_ttl_timeout = 60;

INSERT INTO TABLE ttl_table_test VALUES(now()-interval 9 minute,1),(now()-interval 8 minute,2),(now()-interval 7 minute,3);

SELECT * FROM ttl_table_test;

上诉sql指令首先创建了一个TTL表ttl_table_test并设置了超时时间为10分钟,后续修改了计划外合并的周期为60秒(默认为86400秒,一天),之后向表中插入了3条数据,这3条数据分别会在1分钟后、2分钟后、3分钟后过期。最后查询表中的数据。

INSERT INTO TABLE ttl_table_test VALUES(now()-interval 10 minute,1),(now()-interval 9 minute,2),(now()-interval 8 minute,3);

如果往TTL表里插入已过时数据,则已过时数据不会被存储下来。

merge_with_ttl_timeout时间窗口内未进行后台或强制OPTIMIZE合并表,已经过期的数据就会还在,所以会查询到过期的数据。

使用

ALTER TABLE ttl_table_test MODIFY SETTING merge_with_ttl_timeout = 60;

merge_with_ttl_timeout设定为60秒,可以很快验证过期数据是否被删除(P.S. 设定过低会频繁执行合并,耗费系统资源。)或者先进行OPTIMIZE再查询

OPTIMIZE TABLE ttl_table_test final;

可以看到过期数据已经不存在了。

参考文献

  1. clickhouse.tech