1 需要的依赖pom文件
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-scala-bridge_${
scala.binary.version}</artifactId>
<version>1.10.0</version>
<!-- <scope>provided</scope>-->
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner_2.11</artifactId>
<version>1.10.0</version>
<!-- <scope>provided</scope>-->
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner-blink_2.11</artifactId>
<version>1.10.0</version>
<!-- <scope>provided</scope>-->
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-common</artifactId>
<version>1.10.0</version>
<!-- <scope>provided</scope>-->
</dependency>
1.1 流程
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")
2 创建环境
2.1 基于流处理执行环境,调 create 方法直接创建
val tableEnv = StreamTableEnvironment.create(env)
表环境(TableEnvironment)是 flink 中集成 Table API & SQL 的核心概念。它负责:
• 注册 catalog
• 在内部 catalog 中注册表
• 执行 SQL 查询
• 注册用户自定义函数
• 将 DataStream 或 DataSet 转换为表
• 保存对 ExecutionEnvironment 或 StreamExecutionEnvironment 的引用
在创建 TableEnv 的时候,可以多传入一个 EnvironmentSettings 或者 TableConfig 参数,可以
用来配置 TableEnvironment 的一些特性。
2.2 配置老版本的流式查询(Flink-Streaming-Query)
val settings = EnvironmentSettings
.newInstance()
.useOldPlanner() // 使用老版本 planner
.inStreamingMode() // 流处理模式
.build()
val tableEnv = StreamTableEnvironment.create(env, settings)
2.3 基于老版本的批处理环境(Flink-Batch-Query)
val batchEnv = ExecutionEnvironment.getExecutionEnvironment
val batchTableEnv = BatchTableEnvironment.create(batchEnv)
2.4 基于 blink 版本的流处理环境(Blink-Streaming-Query)
val bsSettings = EnvironmentSettings
.newInstance()
.useBlinkPlanner()
.inStreamingMode()
.build()
val bsTableEnv = StreamTableEnvironment.create(env, bsSettings)
2.5 基于 blink 版本的批处理环境(Blink-Batch-Query)
val bbSettings = EnvironmentSettings
.newInstance()
.useBlinkPlanner()
.inBatchMode().build()
val bbTableEnv = TableEnvironment.create(bbSettings)
2.6 案例
package test7
import test2.{
SensorReading, SensorSource}
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.table.api.scala._
import org.apache.flink.api.scala._
import org.apache.flink.table.api.{
DataTypes, EnvironmentSettings, Table}
import org.apache.flink.table.descriptors.{
Csv, FileSystem, Schema}
object FlinkTableExample {
def main(args: Array[String]): Unit = {
// 创建执行环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1)
// 创建表环境, 使用blink planner
val settings = EnvironmentSettings
.newInstance()
.useBlinkPlanner()
.inStreamingMode()
.build()
val tableEnv = StreamTableEnvironment.create(env, settings)
tableEnv
.connect(new FileSystem().path("/Users/yuanzuo/Desktop/flink-tutorial/FlinkSZ1128/src/main/resources/sensor.txt"))
.withFormat(new Csv()) // 按照csv文件格式解析文件
.withSchema( // 定义表结构
new Schema()
.field("id", DataTypes.STRING())
.field("timestamp", DataTypes.BIGINT())
.field("temperature", DataTypes.DOUBLE())
)
.createTemporaryTable("inputTable") // 创建临时表
val sensorTable: Table = tableEnv.from("inputTable") // 将临时表inputTable赋值到sensorTable
// 使用table api
val resultTable: Table = sensorTable
.select("id, temperature") // 查询`id`, `temperature` => (String, Double)
.filter("id = 'sensor_1'") // 过滤
resultTable
.toAppendStream[(String, Double)] // 追加流
.print()
// 使用flink sql的方式查询
val resultSqlTable: Table = tableEnv
.sqlQuery("select id, temperature from inputTable where id ='sensor_1'")
resultSqlTable
.toAppendStream[(String, Double)] // 追加流
.print()
// 将DataStream转换成流表
val stream = env.addSource(new SensorSource)
// 将流转换成了动态表
val table = tableEnv.fromDataStream(stream, 'id, 'timestamp as 'ts, 'temperature as 'temp)
table
.select('id, 'temp) // 生成了另一张动态表
// 将表的每一行转换成`(String, Double)`元组类型
.toAppendStream[(String, Double)] // 将动态表转换成了流
.print()
// 时间属性
// 定义处理时间
val tableProcessingTime = tableEnv
// `'pt.proctime`:添加处理时间,字段名是`'pt`
.fromDataStream(stream, 'id, 'timestamp as 'ts, 'temperature as 'temp, 'pt.proctime)
// 定义事件时间
val tableEventTime = tableEnv
// 将timestamp指定为事件时间,并命名为ts
.fromDataStream(stream, 'id, 'timestamp.rowtime as 'ts, 'temperature as 'temp)
env.execute()
}
}
3 在 Catalog 中注册表
表(Table)的概念 TableEnvironment 可以注册目录 Catalog,并可以基于 Catalog 注册表。它会维护一个 Catalog-Table 表之间的 map。
表(Table)是由一个 “标识符” 来指定的,由 3 部分组成: Catalog 名、数据库(database)名和对象名(表名)。如果没有指定目录或数据库,就使用当前的默认值。表可以是常规的(Table,表),或者虚拟的(View,视图)。常规表(Table)一般可以用来描述外部数据,比如文件、数据库表或消息队列的数据,也可以直接从 DataStream 转换而来。视图可以从现有的表中创建,通常是 table API 或者 SQL 查询的一个结果。
3.1 连接到文件系统(Csv 格式)
连接外部系统在 Catalog 中注册表,直接调用 tableEnv.connect()就可以,里面参数要传入一个 ConnectorDescriptor,也就是 connector 描述器。对于文件系统的 connector 而言, flink 内部已经提供了,就叫做 FileSystem()。
代码如下:
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-csv</artifactId>
<version>1.10.0</version>
</dependency>
tableEnv
.connect(new FileSystem().path("sensor.txt")) // 定义表数据来源,外部连接
.withFormat(new Csv()) // 定义从外部系统读取数据之后的格式化方法
.withSchema(
new Schema()
.field("id", DataTypes.STRING())目录 169
.field("timestamp", DataTypes.BIGINT())
.field(