Flink学习笔记之TableAPI

文章目录

  • Flink中Table API & SQL简单介绍
  • 两个规划者之间的主要差异
  • TableEnvironmetnt认识
  • 表API和SQL程序的结构
  • 创建一个TableEnvironment
    • 开发环境构建
    • TableEnvironment基本操作
      • 内部CataLog注册
        • 内部Table注册
        • TableSource注册
  • 表API
      • Scan, Projection, and Filter
      • Column Operations
      • Aggregations
      • Joins
      • Set Operations
      • OrderBy, Offset & Fetch
      • Insert
      • Group Windows
        • Tumbling Window(滚动窗口)
        • Sliding Window(滑动窗口)
        • Session Window(会话窗口)
      • Over Window
        • Unbounded Over Windows
        • Bounded Over Windows
      • Row-based Operations(基于行操作)
    • 数据类型

Flink中Table API & SQL简单介绍

对于像DataFrame这样的关系型编程接口,因其强大且灵活的表达能力,能够让用户通过非常丰富的接口对数据进行处理,有效降低了用户的使用成本,近年来逐渐成为主流大数据处理框架主要接口形式之一。Flink也提供了关系型编程接口Table API以及基于TableAPISQL API,让用户能够通过使用结构化编程接口高效的构建Flink应用。同时Table API以及SQL能够统一处理批量和实时计算业务,无需切换到修改任何应用代码就能够基于同一套API编写流式应用和批量应用,从而达到真正意义的批流统一。

Apache Flink具有两个关系API - 表APISQL- 用于统一流和批处理。Table APIScalaJava的语言集成查询API,允许以非常直观的方式组合来自关系运算符的查询,Table APISQL接口彼此紧密集成,以及FlinkDataStreamDataSet API。您可以轻松地在基于API构建的所有API和库之间切换。例如,您可以使用CEP库从DataStream中提取模式,然后使用Table API分析模式,或者可以在预处理上运行Gelly图算法之前使用SQL查询扫描,过滤和聚合批处理表数据。

两个规划者之间的主要差异

  1. Blink将批处理作业视为流式传输的特例。因此,也不支持Table和DataSet之间的转换,批处理作业不会转换为Dataset程序,而是转化为DataStream程序,与流作业相同。
  2. Blink planner不支持BatchTableSource,使用有界StreamTableSource而不是它。
  3. Blink规划器仅支持全新Catalog,不支持ExternalCatalog已弃用。
  4. 旧计划程序和Blink计划程序的FilterableTableSource的实现是不兼容的。 旧计划者将PlannerExpressions推向FilterableTableSource,而Blink计划者将推下表达式。
  5. 基于字符串的键值配置选项(有关详细信息,请参阅有关配置的文档)仅用于Blink规划器。
  6. PlannerConfig在两个规划者中的实现(CalciteConfig)是不同的。
  7. Blink规划器将多个接收器优化为一个DAG(仅在TableEnvironment上支持,而不在StreamTableEnvironment上支持)。 旧规划器将始终将每个接收器优化为新的DAG,其中所有DAG彼此独立。
  8. 现在,旧规划器不支持目录统计,而Blink规划器则支持。

TableEnvironmetnt认识

DataStream一样,Table APISQL中具有相同的基本编程模型。首先需要构建对应的TableEnvironment创建关系型编程环境,才能够在程序中使用Table APISQL来编写程序,另外Table APISQL接口可以在应用中同时使用。Flink SQL基于Apache Cacite框架实现SQL协议,是构建在Table API之上的更高级接口。

表API和SQL程序的结构

// JAVA
TableEnvironment tableEnv = ...; // see "Create a TableEnvironment" section

// register a Table
tableEnv.registerTable("table1", ...)            // or
tableEnv.registerTableSource("table2", ...);     // or
tableEnv.registerExternalCatalog("extCat", ...);

// register an output Table
tableEnv.registerTableSink("outputTable", ...);

// create a Table from a Table API query
Table tapiResult = tableEnv.scan("table1").select(...);
// create a Table from a SQL query
Table sqlResult  = tableEnv.sqlQuery("SELECT ... FROM table2 ... ");

// emit a Table API result Table to a TableSink, same for SQL result
tapiResult.insertInto("outputTable");
// execute
tableEnv.execute("java_job");

创建一个TableEnvironment

TableEnvironmentTable APISQL集成的核心概念,他主要负责:

  • Table内部目录中注册表
  • 注册一个外部表
  • 执行SQL查询
  • 注册用户行为的(标量,表或聚合)函数
  • DataStream或者DataSet转换为Table
  • 持有对ExecutionEnvironment或的引用StreamExecutionEnvironment

表始终绑定到特定的TableEnvironment。 不可能在同一查询中组合不同TableEnvironments的表,例如,加入或联合它们。

通过使用StreamExecutionEnvironmentExecutionEnvironment和可选的TableConfig调用静态BatchTableEnvironment.create()StreamTableEnvironment.create()方法来创建TableEnvironmentTableConfig可用于配置TableEnvironment或自定义查询优化和转换过程.

开发环境构建

<dependency>
            <groupId>org.apache.flinkgroupId>
            <artifactId>flink-javaartifactId>
            <version>${flink.version}version>
        dependency>
        <dependency>
            <groupId>org.apache.flinkgroupId>
            <artifactId>flink-coreartifactId>
            <version>${flink.version}version>
        dependency>

        <dependency>
            <groupId>org.apache.flinkgroupId>
            <artifactId>flink-streaming-java_${scala.binary.version}artifactId>
            <version>${flink.version}version>
        dependency>
        
        <dependency>
            <groupId>org.apache.flinkgroupId>
            <artifactId>flink-table-api-java-bridge_${scala.binary.version}artifactId>
            <version>${flink.version}version>
        dependency>
        <dependency>
            <groupId>org.apache.flinkgroupId>
            <artifactId>flink-table-planner_${scala.binary.version}artifactId>
            <version>${flink.version}version>
        dependency>
        <dependency>
            <groupId>org.apache.flinkgroupId>
            <artifactId>flink-table-commonartifactId>
            <version>${flink.version}version>
        dependency>

Note 1 : 由于Flink Table接口中引入了Apache Calcite第三方库,会阻止Java虚拟机对用户的Classloaders进行垃圾回收,因此不建议用户在构建Flink应用时将flink table依赖包打包进fat-jar中,可以在集群环境中将{FLINK_HOME}/opt的对应的flink-table jar复制到{FLINK_HOME}/lib中解决此类问题。

Note 2 : If there is only one planner jar in /lib directory, you can use useAnyPlanner (use_any_planner for python) to create specific EnvironmentSettings.

TableEnvironment基本操作

使用Table API & SQL创建Flink应用程序,需要在环境中创建TableEnvironment对象,TableEnvironment提供了注册内部表,执行Flink SQL语句、注册自定义函数等功能。

// 批处理环境
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
// 获取表操作环境对象
BatchTableEnvironment tableEnvironment = BatchTableEnvironment.create(env);

// 流处理环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 获取表操作环境对象
StreamTableEnvironment tableEnvironment = StreamTableEnvironment.create(env);

内部CataLog注册

内部Table注册

在获取TableEnvironment对象后,可以使用TableEnvironment提供的方法来注册相应的数据源和数据表信息。所有对数据库和数据表的元数据信息存放在Flink CataLog内部目录中,其存放了Flink内部所有与Table相关的元数据信息,包括表的结构信息,数据源信息等。

Table nameSumDeptid = tableEnvironment.scan("emp").select("name,deptid,email");
// 将 nameSumDeptid 在CataLog中注册成内部表 nameTable
tableEnvironment.registerTable("nameTable" , nameSumDeptid)
TableSource注册

在使用Table API,可以将外部数据源直接注册成Table数据结构。

// 批处理环境
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
// 获取表操作环境对象
BatchTableEnvironment tableEnvironment = BatchTableEnvironment.create(env);
// 创建csv文件类型的TableSource
TableSource csvSource = new CsvTable("/file.csv" , ",");
// 将创建好的TableSource注册到BatchTableEnvironment
tableEnvironment.registerTableSource("CsvTable" , csvSource);

表API

扫描表Orders,并按照a字段进行分组聚合,查找ab的数量并将b的计数取名为cnt

Table orders = tEnv.scan("Orders"); // schema (a, b, c, rowtime)
Table counts = orders
        .groupBy("a")
        .select("a, b.count as cnt");

// conversion to DataSet
DataSet<Row> result = tEnv.toDataSet(counts, Row.class);
result.print();

下一个示例显示了一个更复杂的Table API程序。程序再次扫描Orders表格。它过滤空值,规范化aString类型的字段,并计算每小时和产品a的平均计费金额b

Table orders = tEnv.scan("Orders"); // schema (a, b, c, rowtime)

Table result = orders
        .filter("a.isNotNull && b.isNotNull && c.isNotNull")
        .select("a.lowerCase() as a, b, rowtime")
        .window(Tumble.over("1.hour").on("rowtime").as("hourlyWindow"))
        .groupBy("hourlyWindow, a")
        .select("a, hourlyWindow.end as hour, b.avg as avgBillingAmount");

Scan, Projection, and Filter

Operators Description
Scan
与SQL查询中的FROM子句类似。 执行已注册表的扫描.
Table orders = tableEnv.scan("Orders");
Select 与SQL SELECT语句类似。 执行选择操作。
Table orders = tableEnv.scan("Orders");
Table result = orders.select("a, c as d");
You can use star (*) to act as a wild card, selecting all of the columns in the table.
Table result = orders.select("*");
As Renames fields.Table orders = tableEnv.scan("Orders"); Table result = orders.as("x, y, z, t");
Where / Filter 与SQL WHERE子句类似。 过滤掉未通过过滤谓词的行.
Table orders = tableEnv.scan("Orders");
Table result = orders.where("b === 'red'");
Table orders = tableEnv.scan("Orders"); Table result = orders.filter("a % 2 === 0");

Column Operations

Operators Description
AddColumns 执行字段添加操作。 如果添加的字段已存在,它将抛出异常。
Table orders = tableEnv.scan("Orders");
Table result = orders.addColumns("concat(c, 'sunny')");
AddOrReplaceColumns 执行字段添加操作。 如果添加列名称与现有列名称相同,则将替换现有字段。 此外,如果添加的字段具有重复的字段名称,则使用最后一个字段。
Table orders = tableEnv.scan("Orders");
Table result = orders.addOrReplaceColumns("concat(c, 'sunny') as desc");
DropColumns 执行字段放置操作。 字段表达式应该是字段引用表达式,并且只能删除现有字段.
Table orders = tableEnv.scan("Orders"); Table result = orders.dropColumns("b, c");
RenameColumns 执行字段重命名操作。 字段表达式应该是别名表达式,并且只能重命名现有字段。
Table orders = tableEnv.scan("Orders");
Table result = orders.renameColumns("b as b2, c as c2");

Aggregations

Operators Description
GroupBy Aggregation 与SQL GROUP BY子句类似。使用以下运行的聚合运算符对分组键上的行进行分组,以按组聚合行。
Table orders = tableEnv.scan("Orders");
Table result = orders.groupBy(“a”).select(“a, b.sum as d”);`
Note: 对于流式查询,计算查询结果所需的状态可能会无限增长,具体取决于聚合类型和不同分组键的数量。请提供具有有效保留间隔的查询配置,以防止状态过大
GroupBy Window Aggregation 组和聚合组窗口上的表以及可能的一个或多个分组键。
Flink学习笔记之TableAPI_第1张图片
Over Window Aggregation Streaming 类似于SQL OVER子句。基于前一行和后一行的窗口(范围)计算每行的窗口聚合Flink学习笔记之TableAPI_第2张图片
Note: 必须在同一窗口中定义所有聚合,即相同的分区,排序和范围。目前,仅支持具有PRREDING(UNBOUNDED和有界)到CURRENT ROW范围的窗口。尚不支持使用FOLLOWING的范围。必须在单个时间属性上指定ORDER BY 。
Distinct Aggregation 类似于SQL DISTINCT聚合子句,例如COUNT(DISTINCT a)。不同聚合声明聚合函数(内置或用户定义)仅应用于不同的输入值。Distinct可以应用于GroupBy聚合GroupBy窗口聚合Over Window Aggregation
Flink学习笔记之TableAPI_第3张图片
Note: 用户定义的聚合函数也可以与DISTINCT修饰符一起使用。要仅为不同的值计算聚合结果,只需将distinct修饰符添加到聚合函数即可。
[外链图片转存失败Flink学习笔记之TableAPI_第4张图片
Note: 对于流式查询,计算查询结果所需的状态可能会无限增长,具体取决于不同字段的数量。请提供具有有效保留间隔的查询配置,以防止状态过大。
Distinct 与SQL DISTINCT子句类似。返回具有不同值组合的记录。
[外链图片转存失败在这里插入图片描述
对于流式查询,计算查询结果所需的状态可能会无限增长,具体取决于不同字段的数量。请提供具有有效保留间隔的查询配置,以防止状态过大。如果启用了状态清除,则distinct必须发出消息以防止下游运营商的过早状态驱逐,这使得distinct包含结果更新.

Joins

Operators Description
Inner Join 与SQL JOIN子句类似。加入两张桌子。两个表必须具有不同的字段名称,并且必须通过连接运算符或使用where或filter运算符定义至少一个相等连接谓词。
在这里插入图片描述
**Note ?*对于流式查询,计算查询结果所需的状态可能会无限增长,具体取决于不同输入行的数量。请提供具有有效保留间隔的查询配置,以防止状态过大
Outer Join 与SQL LEFT / RIGHT / FULL OUTER JOIN子句类似。加入两张桌子。两个表必须具有不同的字段名称,并且必须至少定义一个相等连接谓词。
Flink学习笔记之TableAPI_第5张图片
Time-windowed Join 时间窗口连接是可以以流方式处理的常规连接的子集。
时间窗口连接需要至少一个等连接谓词和一个限制双方时间的连接条件。这样的条件可以由两个适当的范围谓词(<, <=, >=, >)或单个等式谓词来定义,该单个等式谓词比较两个输入表的相同类型的时间属性(即,处理时间或事件时间)。
Flink学习笔记之TableAPI_第6张图片
Inner Join with Table Function 使用表函数的结果连接表。 左(外)表的每一行与表函数的相应调用产生的所有行连接。 如果其表函数调用返回空结果,则删除左(外)表的一行。
Flink学习笔记之TableAPI_第7张图片
Left Outer Join with Table Function 使用表函数的结果连接表。 左(外)表的每一行与表函数的相应调用产生的所有行连接。 如果表函数调用返回空结果,则保留相应的外部行,并使用空值填充结果。
Flink学习笔记之TableAPI_第8张图片
Join with Temporal Table 时态表是跟踪随时间变化的表。
时态表函数提供对特定时间点的时态表的状态的访问。 使用时态表函数连接表的语法与使用表函数的内部连接相同。
目前仅支持具有时态表的内部联接。
Flink学习笔记之TableAPI_第9张图片

Set Operations

Operators Description
Union 与SQL UNION子句类似。 联合两个表删除了重复记录。 两个表必须具有相同的字段类型。
在这里插入图片描述
UnionAll 类似于SQL UNION ALL子句。 工会两张桌子。 两个表必须具有相同的字段类型。
在这里插入图片描述
Intersect 类似于SQL INTERSECT子句。 Intersect返回两个表中存在的记录。 如果一个或两个表不止一次出现记录,则只返回一次,即结果表没有重复记录。 两个表必须具有相同的字段类型。
在这里插入图片描述
IntersectAll 类似于SQL INTERSECT ALL子句。 IntersectAll返回两个表中存在的记录。 如果两个表中的记录多次出现,则返回的次数与两个表中的记录一样多,即结果表可能具有重复记录。 两个表必须具有相同的字段类型。
在这里插入图片描述
Minus 与SQL EXCEPT子句类似。 减号返回左表中右表中不存在的记录。 左表中的重复记录只返回一次,即删除重复项。 两个表必须具有相同的字段类型。
在这里插入图片描述
MinusAll 类似于SQL EXCEPT ALL子句。 MinusAll返回右表中不存在的记录。 在左表中出现n次并在右表中出现m次的记录返回(n-m)次,即,删除右表中出现的重复数。 两个表必须具有相同的字段类型。
在这里插入图片描述
In 与SQL IN子句类似。 如果表达式存在于给定的表子查询中,则返回true。 子查询表必须包含一列。 此列必须与表达式具有相同的数据类型。Flink学习笔记之TableAPI_第10张图片

OrderBy, Offset & Fetch

Operators Description
Order By 与SQL ORDER BY子句类似。 返回跨所有并行分区全局排序的记录。在这里插入图片描述
Offset & Fetch 类似于SQL OFFSET和FETCH子句。 偏移和提取限制从排序结果返回的记录数。 Offset和Fetch在技术上是Order By运算符的一部分,因此必须以它为前缀。Flink学习笔记之TableAPI_第11张图片

Insert

Operators Description
Insert Into 类似于SQL查询中的INSERT INTO子句。 执行插入已注册的输出表。在这里插入图片描述

Group Windows

Group WindowDataStream APIDataSet API中提供的窗口一致,都是将流式数据集根据窗口;类型切分为有界数据集,然后在有界数据集上进行聚合类运算。

tableEnv.scan("Sensors")
    .winwods([w : Window] as "window") // 指定窗口类型,并命名为window
    .groupBy("window") // 根据窗口进行聚合,窗口数据会分配到单个Task算子中
    .select("varl1.sum") // 指定对var字段进行Sum求和

在流式计算中,GroupBy聚合条件可以以上实例选择Window名称,也可以是一个或多个Key值与Window的组合。

  • 如果指定Window名称,则和Global Window相似,窗口中的数据都会被汇总到一个Task线程中处理,统计窗口全局的结果;
  • 如果指定KeyWindow名称组合,则窗口中的数据分布到并行计算的算子实例中去计算结果。
tableEnv.scan("Sensors")
    .window([w:Window] as "window") // 
    .groupBy("window" , "id") // 根据窗口聚合,窗口数据分配到每单个Task算子
    .select("id" , "var1.sum") // 指定val字段求和

select语句中,我们除了可以获取到数据元素以外,还可以获取到窗口的元数据信息。

tableEnv.scan("Sensors")
    .window([w:Window] as "window") // 
    .groupBy("window" , "id") // 根据窗口聚合,窗口数据分配到每单个Task算子
    .select("id" , "var1.sum","window.start","window.end","window.rowtime") // 指定val字段求和

**Note : ** 在以上window()方法中需要指定的是不同的窗口类型,已确定数据元素被分配到窗口的逻辑。在Table API中支持Tumble , Sliding , Session Window三种窗口类型,并分别通过不同的Window对象来完成定义。

Tumbling Window(滚动窗口)

前面提到滚动窗口的窗口长度是固定的,窗口之间的数据不会重合。滚动窗口可以基于Evenet TimeProcess Time以及Row-Count来定义。如下实例:Table API中滚动窗口使用Tumble Class来创建,且分别基于Evenet TimeProcess Time以及Row-Count来定义窗口。

// 通过scan方法在CataLog中查询Sensors表
tableEnv.scan("Sensors")
    // Tumbling Event-time Window
    .window(Tumble.over("10.minutes").on("rowtime").as("w"));
    // Tumbling Processing-time Window (assuming a processing-time attribute "proctime")
    .window(Tumble.over("10.minutes").on("proctime").as("w"));
    // Tumbling Row-count Window (assuming a processing-time attribute "proctime")
    .window(Tumble.over("10.rows").on("proctime").as("w"));
  • over : 指定窗口的长度
  • on : 定义了窗口基于的时间概念类型为EventTime还是ProcessTimeEventTime对应着rowtimeProcessTime对应着proctime
  • as : 将创建的窗口重命名,同时窗口名称需要在后续的孙子中使用。
Sliding Window(滑动窗口)

滑动窗口的长度也是固定的,但窗口与窗口之间的数据能够重合。滑动窗口可以基于Evenet TimeProcess Time以及Row-Count来定义。如下实例:Table API中滑动窗口使用Slide Class来创建,且分别基于Evenet TimeProcess Time以及Row-Count来定义窗口。

// 通过scan方法在CataLog中查询Sensors表
tableEnv.scan("Sensors")
    // Sliding Event-time Window
    .window(Slide.over("10.minutes").every("5.minutes").on("rowtime").as("w"));
    // Sliding Processing-time window (assuming a processing-time attribute "proctime")
    .window(Slide.over("10.minutes").every("5.minutes").on("proctime").as("w"));
    // Sliding Row-count window (assuming a processing-time attribute "proctime")
    .window(Slide.over("10.rows").every("5.rows").on("proctime").as("w"));
  • over : 定义窗口的长度,可以是时间或行计数间隔。
  • every : 定义滑动间隔,可以是时间间隔也可以是行数。滑动间隔必须与大小间隔的类型相同。
  • on : 定义了窗口基于的时间概念类型为EventTime还是ProcessTimeEventTime对应着rowtimeProcessTime对应着proctime
  • as : 将创建的窗口重命名,同时窗口名称需要在后续的孙子中使用。
Session Window(会话窗口)

TumblingSliding 窗口不同的是,Session窗口不需要指定固定的窗口时间,而是通过判断固定时间内数据的活跃性来切分窗口。例如 10 min内数据不接入则切分窗口并触发计算。Session窗口只能基于EventTimeProcessTime时间概念来定义,通过withGrap操作符指定数据不活跃的时间Grap,表示超过该时间数据不接入,则切分窗口并触发计算。

// 通过scan方法在CataLog中查询Sensors表
tableEnv.scan("Sensors")
    // Session Event-time Window
    .window(Session.withGap("10.minutes").on("rowtime").as("w"));
    // Session Processing-time Window (assuming a processing-time attribute "proctime")
    .window(Session.withGap("10.minutes").on("proctime").as("w"));

Over Window

Over Window和标准SQL中提供的Over语法功能类似,也是一种数据聚合计算的方式,但和Group Window不同的是,Over Window不需要对输入数据按照窗口大小进行堆叠。Over Window是基于当前数据和其周围邻近范围内数据进行聚合统计的,例如基于当前记录前面的20条数据,然后基于这些数据统计某一指标的聚合结果。

Table API中,Over Window也是在window方法中指定,但后面不需要和groupBy操作符绑定,后面直接接SELECT操作符,并在select操作符中指定需要查询字段和聚合指标。

Table table = input
  .window([OverWindow w].as("w"))           // define over window with alias w
  .select("a, b.sum over w, c.min over w"); // aggregate over the over window w
方法 需要 描述
partitionBy 可 选的 定义一个或多个属性上的输入分区。每个分区都是单独排序的,聚合函数分别应用于每个分区。
**注意:**在流式环境中,如果窗口包含partition by子句,则只能并行计算窗口聚合。没有partitionBy(...)流由单个非并行任务处理。
orderBy 需要 定义每个分区中行的顺序,从而定义聚合函数应用于行的顺序。
**注意:**对于流式查询,这必须是声明的事件时间或处理时间属性。目前,仅支持单个排序属性。
preceding 可选的 定义窗口中包含的行的间隔,并在当前行之前。间隔可以指定为时间或行计数间隔。在窗口上限定具有间隔的大小,例如,10.minutes时间间隔或10.rows行计数间隔。使用常量(即,UNBOUNDED_RANGE时间间隔或UNBOUNDED_ROW行计数间隔)指定在窗口上无界限。在Windows上无限制地从分区的第一行开始。如果preceding条款被省略,UNBOUNDED_RANGE并且CURRENT_RANGE被用作默认precedingfollowing用于该窗口。
following 可选的 定义窗口中包含的行的窗口间隔,并跟随当前行。必须在与前一个间隔(时间或行计数)相同的单位中指定间隔。目前,不支持在当前行之后包含行的窗口。相反,您可以指定两个常量之一:CURRENT_ROW 将窗口的上限设置为当前行。CURRENT_RANGE 设置窗口的上限以对当前行的排序键进行排序,即窗口中包含与当前行具有相同排序键的所有行。如果following省略该子句,则将时间间隔窗口CURRENT_RANGE的上限定义为,并将行计数间隔窗口的上限定义为CURRENT_ROW
as 需要 为覆盖窗口指定别名。别名用于引用以下select()子句中的over window 。

Note : 目前,同一select()调用中的所有聚合函数必须计算相同的窗口。

Unbounded Over Windows
// Unbounded Event-time over window (assuming an event-time attribute "rowtime")
.window(Over.partitionBy("a").orderBy("rowtime").preceding("unbounded_range").as("w"));

// Unbounded Processing-time over window (assuming a processing-time attribute "proctime")
.window(Over.partitionBy("a").orderBy("proctime").preceding("unbounded_range").as("w"));

// Unbounded Event-time Row-count over window (assuming an event-time attribute "rowtime")
.window(Over.partitionBy("a").orderBy("rowtime").preceding("unbounded_row").as("w"));

// Unbounded Processing-time Row-count over window (assuming a processing-time attribute "proctime")
.window(Over.partitionBy("a").orderBy("proctime").preceding("unbounded_row").as("w"));
Bounded Over Windows
// Bounded Event-time over window (assuming an event-time attribute "rowtime")
.window(Over.partitionBy("a").orderBy("rowtime").preceding("1.minutes").as("w"))

// Bounded Processing-time over window (assuming a processing-time attribute "proctime")
.window(Over.partitionBy("a").orderBy("proctime").preceding("1.minutes").as("w"))

// Bounded Event-time Row-count over window (assuming an event-time attribute "rowtime")
.window(Over.partitionBy("a").orderBy("rowtime").preceding("10.rows").as("w"))

// Bounded Processing-time Row-count over window (assuming a processing-time attribute "proctime")
.window(Over.partitionBy("a").orderBy("proctime").preceding("10.rows").as("w"))

Row-based Operations(基于行操作)

The row-based operations generate outputs with multiple columns.

Operators Describtion
Map 使用用户定义的标量函数或内置标量函数执行映射操作。如果输出类型是复合类型,则输出将被展平。Flink学习笔记之TableAPI_第12张图片
FlatMap Flink学习笔记之TableAPI_第13张图片
Aggregate Flink学习笔记之TableAPI_第14张图片
FlatAggregate Flink学习笔记之TableAPI_第15张图片
Group Window FlatAggregate Flink学习笔记之TableAPI_第16张图片

数据类型

Flink学习笔记之TableAPI_第17张图片

你可能感兴趣的:(Flink)