时间属性(time attributes)其实就是每个表模式结构(schema)的一部分。它可以在创建表的 DDL 里直接定义为一个字段,也可以在 DataStream 转换成表时定义。一旦定义了时间属性,它就可以作为一个普通字段引用,并且可以在基于时间的操作中使用。时间属性的数据类型为 TIMESTAMP,它的行为类似于常规时间戳,可以直接访问并且进行计算。
按照时间语义的不同,我们可以把时间属性的定义分成事件时间(event time)和处理时
间(processing time)两种情况
事件时间语义最大的用途就是处理乱序事件或者延迟事件的场景。我们通过设置水位线
(watermark)来表示事件时间的进展,而水位线可以根据数据的最大时间戳设置一个延迟时
间。这样即使在出现乱序的情况下,对数据的处理也可以获得正确的结果。
CREATE TABLE user_actions (user_name STRING,data STRING,url stringuser_action_time TIMESTAMP(3),-- 使⽤下⾯这句来将 user_action_time 声明为事件时间,并且声明 watermark 的生成规则,即 user_action_time 减 5 秒WATERMARK FOR user_action_time AS user_action_time - INTERVAL '5' SECOND,-- 事件时间列的字段类型必须是 TIMESTAMP 或者 TIMESTAMP_LTZ 类型,如果不是需特殊处理--user_action_time AS TO_TIMESTAMP(FROM_UNIXTIME(相应时间字段, 'yyyy-MM-dd HH:mm:ss')), --WATERMARK FOR user_action_time as user_action_time - INTERVAL '5' SECOND,
) WITH (...
);SELECT user_name,TUMBLE_START(user_action_time, INTERVAL '10' MINUTE),COUNT(url)
FROM user_actions
GROUP BY user_name,TUMBLE(user_action_time, INTERVAL '10' MINUTE)
;
// 方法一:
// 流中数据类型为二元组 Tuple2,包含两个字段;需要自定义提取时间戳并生成水位线
DataStream> stream =
inputStream.assignTimestampsAndWatermarks(...);
// 声明一个额外的逻辑字段作为事件时间属性
Table table = tEnv.fromDataStream(stream, $("user"), $("url"),
$("ts").rowtime());
处理时间就是我们的系统时间,使用时不需要提取时间戳(timestamp)和生成水位线(watermark)。因此在定义处理时间属性时,必须要额外声明一个字段,专门用来保存当前的处理时间。
CREATE TABLE user_actions (user_name STRING,data STRING,url string-- 使⽤下⾯这句来将 user_action_time 声明为处理时间proc AS PROCTIME()
) WITH (...
);SELECT user_name,HOP(proc, INTERVAL '2' MINUTE, INTERVAL '10' MINUTE),COUNT(url)
FROM user_actions
GROUP BY user_name,HOP(proc, INTERVAL '2' MINUTE, INTERVAL '10' MINUTE)
;
DataStream> stream = ...;
// 声明一个额外的字段作为处理时间属性字段
Table table = tEnv.fromDataStream(stream, $("user"), $("url"),
$("ts").proctime());
在实际应用中,很多状态会随着时间的推移逐渐增长,如果不加以限制,最终就会导致存储空间的耗尽。一个优化的思路是直接在代码中调用.clear()方法去清除状态,但是有时候我们的逻辑要求不能直接清除。这时就需要配置一个状态的“生存时间”(time-to-live,TTL),当状态在内存中存在的时间超出这个值时,就将它清除。
//方法1
//环境中配置状态的生存时间(TTL):
TableEnvironment tableEnv = ...
// 获取表环境的配置
TableConfig tableConfig = tableEnv.getConfig();
// 配置状态保持时间
tableConfig.setIdleStateRetention(Duration.ofMinutes(60));//方法2
//可以直接设置配置项 table.exec.state.ttl:
TableEnvironment tableEnv = ...
Configuration configuration = tableEnv.getConfig().getConfiguration();
configuration.setString("table.exec.state.ttl", "60 min");
public void open(Configuration parameters) throws Exception {super.open(parameters);StateTtlConfig ttlConfig = StateTtlConfig// 设置超时时间,超过24小时后,就会被清除.newBuilder(Time.hours(24))//当状态写入和创建的时候刷新ttl.setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite).setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired).build();}