Table API和Flink SQL
整体介绍
Flink
本身是批流统一的处理框架,所以Table API
和 SQL
,就是批流统一的上层处理 API
。 目前功能尚未完善,处于活跃的开发阶段。 Table API
是一套内嵌在 Java
和 Scala
语言中的查询 API
,它允许我们以非常直观的方式, 组合来自一些关系运算符的查询(比如 select
、filter 和join
)。而对于 Flink SQL
,就是直接可 以在代码中写 SQL
,来实现一些查询(Query
)操作。Flink
的 SQL
支持,基于实现了 SQL
标 准的 Apache Calcite
(Apache
开源 SQL
解析工具)。 无论输入是批输入还是流式输入,在这两套 API
中,指定的查询都具有相同的语义,得 到相同的结果。
需要引入的依赖 Table API
和 SQL
需要引入的依赖有两个:planner
和 bridge
。
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner_2.12</artifactId>
<version>1.10.1</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-scala-bridge_2.12</artifactId>
<version>1.10.1</version>
</dependency>
两种planner
(old & blink
)的区别
-
批流统一:
Blink
将批处理作业,视为流式处理的特殊情况。所以,blink
不支持表和DataSet
之间的转换,批处理作业将不转换为DataSet
应用程序,而是跟流处理一样,转换 为DataStream
程序来处理。 -
因 为 批 流 统 一 ,
Blink planner
也 不 支 持BatchTableSource
, 而 使 用 有 界 的StreamTableSource
代替。 -
Blink planner
只支持全新的目录,不支持已弃用的ExternalCatalog
。 -
旧
planner
和Blink planner
的FilterableTableSource
实现不兼容。旧的planner
会把PlannerExpressions
下推到filterableTableSource
中,而blink planner
则会把Expressions
下推。 -
基于字符串的键值配置选项仅适用于
Blink planner
。 -
PlannerConfig
在两个planner
中的实现不同。 -
Blink planner
会将多个sink
优化在一个DAG
中(仅在TableEnvironment
上受支持,而 在StreamTableEnvironment
上不受支持)。而旧planner
的优化总是将每一个sink
放在一个新 的DAG
中,其中所有DAG
彼此独立。 -
旧的
planner
不支持目录统计,而Blink
API的调用
执行环境的创建
程序的基本结构
Table API
和 SQL
的程序结构,与流式处理的程序结构类似;也可以近似地认为有这么 几步:首先创建执行环境,然后定义 source
、transform
和 sink
。
具体操作流程如下:
// 创建表的执行环境
val tableEnv = ...
// 创建一张表,用于读取数据
tableEnv.connect(...).createTemporaryTable("inputTable")
// 注册一张表,用于把计算结果输出
tableEnv.connect(...).createTemporaryTable("outputTable")
// 通过 Table API 查询算子,得到一张结果表
val result = tableEnv.from("inputTable").select(...)
// 通过 SQL 查询语句,得到一张结果表
val sqlResult = tableEnv.sqlQuery("SELECT ... FROM inputTable ...")
// 将结果表写入输出表中
result.insertInto("outputTable")
一个练习,读取本地文件里的数据创建表
读取本地文件
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1)
val filePath = "src/main/resources/SensorReading"
val inputStream = env.readTextFile(filePath)
//转换成样例类
val dataStream = inputStream
.map(data => {
val arr = data
.split(",")
SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
})
Table API
的使用
/**
* Table API的使用
*/
//创建表的执行环境
val tableEnv = StreamTableEnvironment.create(env)
//基于流创建表
val dataTable = tableEnv.fromDataStream(dataStream)
//调用table API转换
val resultTable = dataTable
.select("id, temperature")
.filter("id == 'sensor_1'")
resultTable.toAppendStream[(String, Double)].print("result")
SQL
的使用
/**
* 直接使用SQL实现
*/
//创建表
tableEnv.createTemporaryView("data", dataTable)
val sql = "select id,temperature from data where id = 'sensor_1'"
val resutlSQLTable = tableEnv.sqlQuery(sql)
resutlSQLTable.toAppendStream[(String, Double)].print("SQLResult")
程序环境的创建
创建表环境最简单的方式,就是基于流处理执行环境,调create
方法直接创建:
val tableEnv = StreamTableEnvironment.create(env)
表环境(TableEnvironment
)是 flink
中集成 Table API & SQL
的核心概念。它负责
-
注册
catalog
-
在内部
catalog
中注册表 -
**执行
SQL
查询 ** -
注册用户自定义函数
-
将
DataStream
或DataSet
转换为表 -
保存对
ExecutionEnvironment
或StreamExecutionEnvironment
的引
在创建TableEnv
的时候,可以多传入一个EnvironmentSettings
或者 TableConfig
参数, 可以用来配置 TableEnvironment
的一些特性。
比如,配置老版本的流式查询(Flink-Streaming-Query
):
val settings = EnvironmentSettings.newInstance()
.useOldPlanner() // 使用老版本 planner
.inStreamingMode() // 流处理模式
.build()
val tableEnv = StreamTableEnvironment.create(env, settings)
基于老版本的批处理环境(Flink-Batch-Query
),新版本是批流合一的,但是老版本不是,所以需要创建一个批处理
val batchEnv = ExecutionEnvironment.getExecutionEnvironment
val batchTableEnv = BatchTableEnvironment.create(batchEnv)
基于 blink 版本的流处理环境(Blink-Streaming-Query
):
val bsSettings = EnvironmentSettings.newInstance()
.useBlinkPlanner()
.inStreamingMode().build()
val bsTableEnv = StreamTableEnvironment.create(env, bsSettings)
基于 blink 版本的批处理环境(Blink-Batch-Query
)
val bbSettings = EnvironmentSettings.newInstance()
.useBlinkPlanner()
.inBatchMode().build()
val bbTableEnv = TableEnvironment.create(bbSettings)
读取数据
读取本地文件数据
package TableAndSQL
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.table.api.{
DataTypes, EnvironmentSettings}
import org.apache.flink.table.api.scala.StreamTableEnvironment
import org.apache.flink.table.api.scala._
import org.apache.flink.streaming.api.scala._
import org.apac