Flink SQL 使用时间属性

简介: 事件时间处理时间

在Flink DataStream上做流计算的时候⼀定会涉及时间窗⼝运算,这时候就需要⽤到时间属性,Flink Table API/SQL同样可以使⽤时间属性来⽀持时间窗⼝运算。


时间属性可以是每个表模式的⼀部分,它们是在从 CREATE TABLE DDL 或 DataStream 创建表时定义的。 ⼀旦定 义了时间属性,就可以将其作为字段引⽤并⽤于基于时间的操作。 只要时间属性没有被修改,并且只是从查询的⼀ 部分转发到另⼀部分,它就仍然是有效的时间属性。 时间属性的⾏为类似于常规时间戳,并且可⽤于计算。 在计 算中使⽤时,时间属性被具体化并充当标准时间戳。 但是,普通时间戳不能⽤来代替或转换为时间属性,只有时间 属性字段才能跟⽔印配合使⽤



事件时间


DataStream转Table时定义


方式一


packagecom.blink.sb.time;
importcom.blink.sb.beans.ClickLogs;
importorg.apache.flink.streaming.api.datastream.DataStream;
importorg.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
importorg.apache.flink.table.api.DataTypes;
importorg.apache.flink.table.api.Schema;
importorg.apache.flink.table.api.Table;
importorg.apache.flink.table.api.bridge.java.StreamTableEnvironment;
/*** DataStream转换为Table时指定EventTime属性*/publicclassEventTimeDefDataStream2Table1 {
publicstaticvoidmain(String[] args) throwsException {
//1、获取Stream执行环境StreamExecutionEnvironmentenv=StreamExecutionEnvironment.getExecutionEnvironment();
//2、创建表执行环境StreamTableEnvironmenttEnv=StreamTableEnvironment.create(env);
env.setParallelism(1);
//3、读取数据DataStream<ClickLogs>clickLogs=env.fromElements(
"Mary,./home,2022-02-02 12:00:00",
"Bob,./cart,2022-02-02 12:00:00",
"Mary,./prod?id=1,2022-02-02 12:00:05",
"Liz,./home,2022-02-02 12:01:00",
"Bob,./prod?id=3,2022-02-02 12:01:30",
"Mary,./prod?id=7,2022-02-02 12:01:45"        ).map(event-> {
String[] props=event.split(",");
returnClickLogs                    .builder()
                    .user(props[0])
                    .url(props[1])
                    .cTime(props[2])
                    .build();
        });
//4、流转换为动态表finalSchemaschema=Schema.newBuilder()
                .column("user", DataTypes.STRING())
                .column("url", DataTypes.STRING())
//3就是毫秒,0就是秒                .column("cTime", DataTypes.TIMESTAMP(0))
//以cTime字段减5秒作为水印//                .watermark("cTime", $("cTime").minus(lit(5).seconds()))                .watermark("cTime", "cTime - INTERVAL '5' SECOND")
                .build();
Tabletable=tEnv.fromDataStream(clickLogs,schema);
table.printSchema();
    }
}


注意:这种⽅式⽔印和时间语意⼀起定义,不需要使⽤assignTimestampsAndWatermarks⽅法指定⽔印⽣成策 略。

方式二


packagecom.blink.sb.time;
importcom.blink.sb.beans.ClickLogs;
importorg.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
importorg.apache.flink.api.common.eventtime.WatermarkStrategy;
importorg.apache.flink.streaming.api.datastream.DataStream;
importorg.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
importorg.apache.flink.table.api.Table;
importorg.apache.flink.table.api.bridge.java.StreamTableEnvironment;
importorg.apache.flink.types.Row;
importjava.text.ParseException;
importjava.text.SimpleDateFormat;
importjava.time.Duration;
importstaticorg.apache.flink.table.api.Expressions.$;
/*** DataStream转换为Table时指定EventTime属性*/publicclassEventTimeDefDataStream2Table2 {
publicstaticvoidmain(String[] args) throwsException {
//1、获取Stream执行环境StreamExecutionEnvironmentenv=StreamExecutionEnvironment.getExecutionEnvironment();
//2、创建表执行环境StreamTableEnvironmenttEnv=StreamTableEnvironment.create(env);
env.setParallelism(1);
//3、读取数据并提取时间戳指定水印生成策略WatermarkStrategy<ClickLogs>watermarkStrategy=WatermarkStrategy                .<ClickLogs>forBoundedOutOfOrderness(Duration.ofSeconds(2))
                .withTimestampAssigner(newSerializableTimestampAssigner<ClickLogs>() {
@OverridepubliclongextractTimestamp(ClickLogselement, longrecordTimestamp) {
SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
returnsdf.parse(element.getCTime()).getTime();
                } catch (ParseExceptione) {
e.printStackTrace();
                }
return0;
            }
        });
DataStream<ClickLogs>clickLogs=env.fromElements(
"Mary,./home,2022-02-02 12:00:00",
"Bob,./cart,2022-02-02 12:00:00",
"Mary,./prod?id=1,2022-02-02 12:00:05",
"Liz,./home,2022-02-02 12:01:00",
"Bob,./prod?id=3,2022-02-02 12:01:30",
"Mary,./prod?id=7,2022-02-02 12:01:45"        ).map(event-> {
String[] props=event.split(",");
returnClickLogs                    .builder()
                    .user(props[0])
                    .url(props[1])
                    .cTime(props[2])
                    .build();
        }).assignTimestampsAndWatermarks(watermarkStrategy);
//4、流转换为动态表//当字段名不存在时,重新添加一个字段作为时间属性Tabletable=tEnv.fromDataStream(clickLogs,$("user"),$("url"),$("cTime"),$("eTime").rowtime());
//当字段名存在,且类型为Timestamp或者Long时,直接以现有字段作为时间属性(这里肯定报错)//        Table table = tEnv.fromDataStream(clickLogs,$("user"),$("url"),$("cTime").rowtime());table.printSchema();
//5、转换为流并打印tEnv.toDataStream(table, Row.class).print();
//6、执行env.execute("EventTimeDefDataStream2Table2");
    }
}



在Flink SQL 建表语句中定义


packagecom.blink.sb.time;
importorg.apache.flink.table.api.*;
/*** DDL语句中指定EventTime属性*/publicclassEventTimeDefDDL {
publicstaticvoidmain(String[] args) throwsException {
//1、创建TableEnvironmentEnvironmentSettingssettings=EnvironmentSettings                .newInstance()
                .build();
TableEnvironmenttEnv=TableEnvironment.create(settings);
//2、创建source table(DDL语句)-会自动注册表的tEnv.executeSql("CREATE TABLE user_behavior_log ("+"    user_id BIGINT,"+"    item_id BIGINT,"+"    category_id INT,"+"    behavior VARCHAR,"+//必须是TIMESTAMP"    ts TIMESTAMP(3),"+//声明 ts 为EventTime属性并使用5秒延迟水印策略"    WATERMARK FOR ts AS ts - INTERVAL '5' SECOND"+") WITH ("+"    'connector' = 'filesystem',"+"    'path' = 'data/user_behavior/input/',"+"    'format' = 'csv'"+")");//最后不要有分号,注意空格Tableuser_behavior_log=tEnv.from("user_behavior_log");
user_behavior_log.printSchema();
user_behavior_log.execute().print();
    }
}



处理时间



DataStream转Table时定义


packagecom.blink.sb.time;
importcom.blink.sb.beans.ClickLogs;
importorg.apache.flink.streaming.api.datastream.DataStream;
importorg.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
importorg.apache.flink.table.api.Table;
importorg.apache.flink.table.api.bridge.java.StreamTableEnvironment;
importstaticorg.apache.flink.table.api.Expressions.$;
/*** DataStream转换为Table时指定ProcessTime属性*/publicclassProcessTimeDefDataStream2Table {
publicstaticvoidmain(String[] args) throwsException {
//1、获取Stream执行环境StreamExecutionEnvironmentenv=StreamExecutionEnvironment.getExecutionEnvironment();
//2、创建表执行环境StreamTableEnvironmenttEnv=StreamTableEnvironment.create(env);
env.setParallelism(1);
//3、读取数据DataStream<ClickLogs>clickLogs=env.fromElements(
"Mary,./home,2022-02-02 12:00:00",
"Bob,./cart,2022-02-02 12:00:00",
"Mary,./prod?id=1,2022-02-02 12:00:05",
"Liz,./home,2022-02-02 12:01:00",
"Bob,./prod?id=3,2022-02-02 12:01:30",
"Mary,./prod?id=7,2022-02-02 12:01:45"        ).map(event-> {
String[] props=event.split(",");
returnClickLogs                    .builder()
                    .user(props[0])
                    .url(props[1])
                    .cTime(props[2])
                    .build();
        });
//4、流转换为动态表Tabletable=tEnv.fromDataStream(
clickLogs,
$("user"),
$("url"),
$("cTime"),
$("pt").proctime()
        );
table.printSchema();
table.execute().print();
    }
}



Fink SQL 建表语句中定义


我们可以在DDL语句中,声明⼀个附加字段作为处理时间属性:

packagecom.blink.sb.time;
importorg.apache.flink.table.api.*;
/*** DDL语句中指定ProcessTime属性*/publicclassProcessTimeDefDDL {
publicstaticvoidmain(String[] args) throwsException {
//1、创建TableEnvironmentEnvironmentSettingssettings=EnvironmentSettings                .newInstance()
                .build();
TableEnvironmenttEnv=TableEnvironment.create(settings);
//2、创建source table(DDL语句)-会自动注册表的tEnv.executeSql("CREATE TABLE user_behavior_log ("+"    user_id BIGINT,"+"    item_id BIGINT,"+"    category_id INT,"+"    behavior VARCHAR,"+"    ts BIGINT,"+//声明一个附加字段作为处理时间属性"    user_action_time AS PROCTIME()"+") WITH ("+"    'connector' = 'filesystem',"+"    'path' = 'data/user_behavior/input/',"+"    'format' = 'csv'"+")");//最后不要有分号,注意空格Tableuser_behavior_log=tEnv.sqlQuery("select * from user_behavior_log");
user_behavior_log.printSchema();
user_behavior_log.execute().print();
    }
}


相关实践学习
基于Hologres+Flink搭建GitHub实时数据大屏
通过使用Flink、Hologres构建实时数仓,并通过Hologres对接BI分析工具(以DataV为例),实现海量数据实时分析.
实时计算 Flink 实战课程
如何使用实时计算 Flink 搞定数据处理难题?实时计算 Flink 极客训练营产品、技术专家齐上阵,从开源 Flink功能介绍到实时计算 Flink 优势详解,现场实操,5天即可上手! 欢迎开通实时计算 Flink 版: https://cn.aliyun.com/product/bigdata/sc Flink Forward Asia 介绍: Flink Forward 是由 Apache 官方授权,Apache Flink Community China 支持的会议,通过参会不仅可以了解到 Flink 社区的最新动态和发展计划,还可以了解到国内外一线大厂围绕 Flink 生态的生产实践经验,是 Flink 开发者和使用者不可错过的盛会。 去年经过品牌升级后的 Flink Forward Asia 吸引了超过2000人线下参与,一举成为国内最大的 Apache 顶级项目会议。结合2020年的特殊情况,Flink Forward Asia 2020 将在12月26日以线上峰会的形式与大家见面。
相关文章
|
9月前
|
SQL 人工智能 JSON
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
简介:本文整理自阿里云高级技术专家李麟在Flink Forward Asia 2025新加坡站的分享,介绍了Flink 2.1 SQL在实时数据处理与AI融合方面的关键进展,包括AI函数集成、Join优化及未来发展方向,助力构建高效实时AI管道。
1156 43
|
9月前
|
SQL 人工智能 JSON
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
本文整理自阿里云的高级技术专家、Apache Flink PMC 成员李麟老师在 Flink Forward Asia 2025 新加坡[1]站 —— 实时 AI 专场中的分享。将带来关于 Flink 2.1 版本中 SQL 在实时数据处理和 AI 方面进展的话题。
538 0
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
|
10月前
|
SQL 消息中间件 Kafka
Flink SQL 详解:流批一体处理的强大工具
Flink SQL 是 Apache Flink 提供的 SQL 引擎,支持流批一体处理,统一操作流数据与批数据,具备高性能、低延迟、丰富数据源支持及标准 SQL 兼容性,适用于实时与离线数据分析。
1237 1
|
SQL 存储 API
Flink实践:通过Flink SQL进行SFTP文件的读写操作
虽然 Apache Flink 与 SFTP 之间的直接交互存在一定的限制,但通过一些创造性的方法和技术,我们仍然可以有效地实现对 SFTP 文件的读写操作。这既展现了 Flink 在处理复杂数据场景中的强大能力,也体现了软件工程中常见的问题解决思路——即通过现有工具和一定的间接方法来克服技术障碍。通过这种方式,Flink SQL 成为了处理各种数据源,包括 SFTP 文件,在内的强大工具。
567 15
|
SQL 大数据 数据处理
Flink SQL 详解:流批一体处理的强大工具
Flink SQL 是为应对传统数据处理框架中流批分离的问题而诞生的,它融合了SQL的简洁性和Flink的强大流批处理能力,降低了大数据处理门槛。其核心工作原理包括生成逻辑执行计划、查询优化和构建算子树,确保高效执行。Flink SQL 支持过滤、投影、聚合、连接和窗口等常用算子,实现了流批一体处理,极大提高了开发效率和代码复用性。通过统一的API和语法,Flink SQL 能够灵活应对实时和离线数据分析场景,为企业提供强大的数据处理能力。
2374 27
|
SQL 存储 缓存
Flink SQL Deduplication 去重以及如何获取最新状态操作
Flink SQL Deduplication 是一种高效的数据去重功能,支持多种数据类型和灵活的配置选项。它通过哈希表、时间窗口和状态管理等技术实现去重,适用于流处理和批处理场景。本文介绍了其特性、原理、实际案例及源码分析,帮助读者更好地理解和应用这一功能。
1338 14
|
SQL 大数据 API
大数据-132 - Flink SQL 基本介绍 与 HelloWorld案例
大数据-132 - Flink SQL 基本介绍 与 HelloWorld案例
361 0
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
858 13
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
590 9