Flink 时间特性及sql窗口
文章目录
一、概述
- 基于时间的操作(比如 Table API 和 SQL 中窗口操作),需要定义相关的时间语义和时间数据来源的信息
- Table 可以提供一个逻辑上的时间字段,用于在表处理程序中,指示时间和访问相应的时间戳
- 时间属性,可以是每个表schema的一部分。一旦定义了时间属性,它就可以作为一个字段引用,并且可以在基于时间的操作中使用
- 时间属性的行为类似于常规时间戳,可以访问,并且进行计算
二、定义处理时间(Processing Time)
处理时间语义下,允许表处理程序根据机器的本地时间生成结果。它是时间的最简单概念。它既不需要提取时间戳,也不需要生成 watermark。
由三种方式可以生成proctime:
- 由DataSream转换成表时
- 定义Table Schema时
- 创建表的DDL时
2.1 由DataSream转换成表时
在定义Table Schema期间,可以使用.proctime
,指定字段名义处理时间字段。
proctime属性只能通过附加逻辑字段,来扩展物理schema,因此,只能在schema定义的末尾来定义它。
Table dataTable = tableEnv.fromDataStream(dataStream, "id, timestamp as ts, temperature as temp, **pt.proctime**");
2.2 定义Table Schema时
.withSchema(new Schema()
.field("id", DataTypes.STRING())
.field("timestamp",DataTypes.BIGINT())
.field("temperature",DataTypes.DOUBLE())
.**field("pt",DataTypes.TIMESTAMP(3))**
.**proctime()**
)
2.3 创建表的DDL中
String sinkDDL =
"create table dataTable (" +
" id varchar(20) not null, " +
" ts bigint, " +
" temperature double, " +
" pt AS PROCTIME() " +
" ) with (" +
" 'connector.type' = 'filesystem', " +
" 'connector.path' = '/sensor.txt', " +
" 'format.type' = 'csv')";
tableEnv.sqlUpdate(sinkDDL);
测试代码
package com.root.table;
import com.root.SensorReading;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.java.StreamTableEnvironment;
import org.apache.flink.types.Row;
/**
* @author Kewei
* @Date 2022/3/8 9:37
*/
public class TableTest7_Time {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);
DataStreamSource<String> inputStream = env.readTextFile("data/sensor.txt");
SingleOutputStreamOperator<SensorReading> dataStream = inputStream.map(line -> {
String[] fields = line.split(",");
return new SensorReading(fields[0], new Long(fields[1]), new Double(fields[2]));
})
// DataStream转换为Table,设置当前运行时间pt.proctime
Table dataTable = tableEnv.fromDataStream(dataStream, "id, timestamp as ts, temperature as temp, pt.proctime");
dataTable.printSchema();
tableEnv.toAppendStream(dataTable, Row.class).print();
env.execute();
}
}
三、定义事件时间(Event Time)
- 事件时间语义,允许表处理程序根据每个记录中包含的时间生成结果。这样即使在有乱序事件或者延迟事件时,也可以获得正确的结果。
- 为了处理无序事件,并区分流中的准时和迟到事件;Flink需要从事件数据中,提取时间戳,并用来推送事件时间的进展
- 定义事件事件,同样有三种方法:
- 由DataStream转换成表时指定
- 定义Table Schema时指定
- 在创建表的DDL中定义
3.1 由DataStream转换成表时
- 由DataStream转换成表时,指定时间(推荐)
- 在DataStream转换成Table,使用
.rowtime
可以定义事件事件属性 - 注意需要先指定好事件时间,打开使用事件时间的设置
Table dataTable1 = tableEnv.fromDataStream(dataStream, "id, timestamp.rowtime, temperature");
Table dataTable2 = tableEnv.fromDataStream(dataStream, "id, timestamp, temperature,rt.rowtime");
// rowtime的位置不受限制
3.2 定义Table Schema时
.withSchema(new Schema()
.field("id", DataTypes.STRING())
.field("timestamp",