Flink SQL 使用时间属性

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 事件时间处理时间

在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轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
相关文章
|
9天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标属性:数据的“导航仪”与“仪表盘”
【4月更文挑战第19天】Oracle PL/SQL游标属性如同车辆的导航仪和仪表盘,提供丰富信息和控制。 `%FOUND`和`%NOTFOUND`指示数据读取状态,`%ROWCOUNT`记录处理行数,`%ISOPEN`显示游标状态。还有`%BULK_ROWCOUNT`和`%BULK_EXCEPTIONS`增强处理灵活性。通过实例展示了如何在数据处理中利用这些属性监控和控制流程,提高效率和准确性。掌握游标属性是提升数据处理能力的关键。
|
1月前
|
SQL 资源调度 Oracle
Flink CDC产品常见问题之sql运行中查看日志任务失败如何解决
Flink CDC(Change Data Capture)是一个基于Apache Flink的实时数据变更捕获库,用于实现数据库的实时同步和变更流的处理;在本汇总中,我们组织了关于Flink CDC产品在实践中用户经常提出的问题及其解答,目的是辅助用户更好地理解和应用这一技术,优化实时数据处理流程。
|
1月前
|
SQL 关系型数据库 MySQL
Flink 提供了一种名为 Flink SQL 的查询语言,它支持多种数据库之间的 DDL 语句转换
【2月更文挑战第18天】Flink 提供了一种名为 Flink SQL 的查询语言,它支持多种数据库之间的 DDL 语句转换
171 2
|
1月前
|
SQL 存储 Apache
在 Apache Flink SQL 中,并没有内置的 GROUP_CONCAT 函数
【2月更文挑战第16天】在 Apache Flink SQL 中,并没有内置的 GROUP_CONCAT 函数
198 2
|
1月前
|
SQL 分布式计算 HIVE
基于 Kyuubi 实现分布式 Flink SQL 网关
本文整理自网易互娱资深开发工程师、Apache Kyuubi Committer 林小铂的《基于 Kyuubi 实现分布式 Flink SQL 网关》分享。
104458 64
基于 Kyuubi 实现分布式 Flink SQL 网关
|
2月前
|
SQL 数据采集 JSON
弱结构化日志 Flink SQL 怎么写?SLS SPL 来帮忙
弱结构化日志 Flink SQL 怎么写?SLS SPL 来帮忙
125174 136
|
2月前
|
SQL 监控 API
Flink SQL支持写判断语句
【2月更文挑战第8天】Flink SQL支持写判断语句
236 12
|
2月前
|
SQL 消息中间件 Kafka
flink问题之做实时数仓sql保证分topic区有序如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
707 3
|
2月前
|
SQL 消息中间件 Kafka
Flink报错问题之SQL作业中调用UDTF报错如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
|
2月前
|
SQL 消息中间件 资源调度
Flink报错问题之flink 1.11 sql作业提交JM报错如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。

热门文章

最新文章