概述
Flink具有两个关系型API- Table API和SQL,这两个API,这两个API统一了流处理和批处理。其中Table API是用Scala或者是Java的语言集成查询API。它允许以非常直观的方式从关系运算符(如select、filter和join)组成查询。Flink的SQL支持基于实现SQL标准的Apache Calcite.无论输入的是DataSet(批)还是DataStream(流)这两套接口中指定的查询具有相同的语义和相同的计算结果。
其中Table API和SQL的接口可以紧密的和Flink的Datastream和Dataset集成在一起。因此用户可以在所有的API或者是基于API的库之间轻松切换。例如,用户可以使用CEP Library的库对数据进行模式抽取,然后再使用Table API对抽取的数据进行分析,或者用户可以使用SQL去扫描、过滤和聚合一个批处理的表,然后使用Gelly Graph algorithm进行关系运算等。
依赖结构
从Flink 1.9开始,Flink提供了两种不同的执行计划用于执行Table API或是SQL程序:Blink planner和Flink 1.9之前使用的Old planner。这里的Planner负责将关系运算符翻译成一个可以执行的、优化的Flink job.这两种计算底层使用了不同的优化规则和运行时类,因此它们在支持的功能方面可能有所不同。
注意 对于生成环境使用场景,我们推荐使用flink 1.9之前提供的old planner计划。所有的Table API和SQL组件都绑定在flink-table和flink-table-blink依赖中。下面这些模块在我们开发的时候可能和相关的项目相关
模块名字 | 作用 |
---|---|
flink-table-common | 用于通过自定义function、扩展format等 |
flink-table-api-java | Flink编程中使用纯粹的Java语言编程编写Table API和SQL程序(在早期编程,不推荐) |
flink-table-api-scala | Flink编程中使用纯粹的Scala语言编程编写Table API和SQL程序(在早期编程,不推荐) |
flink-table-api-java-bridge | 在使用Java编写Table API/SQL和Dataset/Datastream |
flink-table-api-scala-bridge | 在使用Scala编写Table API/SQL和Dataset/Datastream |
flink-table-planner | Table program planner和runtime,这是在Flink 1.9之前的唯一计划,在Flink1.11就不在推荐 |
flink-table-planner-blink | 新的Blink planner,在Flink1.11开始被设置为默认执行计划 |
flink-table-runtime-blink | 新的Blink的runtime |
flink-table-uber | 将上面的API以及old planner打包到1个Table&SQL的用例中,默认情况下超级jar文件flink-table-*.jar位于Flink版本的/lib目录下 |
flink-table-uber-blink | 将上面的API以及Blink指定的模块打包到1个Table&SQL的用例中,默认情况下超级jar文件flink-table-blink-*.jar位于Flink版本的/lib目录下 |
用户可以根据自己的编程的目标语言选择合适的依赖,例如
- Java
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-java-bridge_2.11</artifactId>
<version>1.10.0</version>
</dependency>
- Scala
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-scala-bridge_2.11</artifactId>
<version>1.10.0</version>
<scope>provided</scope>
</dependency>
如果用户想在本地的IDE中运行Table API&SQL程序,用户还需要根据自己希望使用到值执行计划的类别,添加不同的执行计划:
- old planner
<!-- Either... (for the old planner that was available before Flink 1.9) -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner_2.11</artifactId>
<version>1.10.0</version>
</dependency>
- Blink planner
<!-- or.. (for the new Blink planner) -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner-blink_2.11</artifactId>
<version>1.10.0</version>
</dependency>
由于底层,Flink Table生态系统一部分的实现是通过Scala实现的,因此无论是执行批处理还是流计算,请确保导入一下依赖:
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_2.11</artifactId>
<version>1.10.0</version>
</dependency>
如果用户想要在连接Kafka的时候实现自定义格式化或者是自定义functions这种场景,用户只需要导入一下依赖即可:
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-common</artifactId>
<version>1.10.0</version>
<scope>provided</scope>
</dependency>
目前这个模块中可以提供的扩展点:SerializationSchemaFactory、DeserializationSchemaFactory、ScalarFunction、TableFunction、AggregateFunction
概念和常见 API
Table API和SQL集成在一个联合API中,该API的概念是一个Table,该Table主要作为查询的输入和输出,接下来来介绍一下Table API和SQL查询的程序的通用结构,其中涵盖如何注册表、查询表以及如何输出表。
两个planner的主要区别
1.Blink中将Batch jobs看作是一个streaming的一个特殊情况,因此还不支持Table和DataSet之间的转换,并且批处理作业不会像流作业一样转换为DataSet程序,而是直接转换为DataStream程序
2.Blink作业不支持BatchTableSource,而是使用StreamTableSource代替
3.Old Planner和Blink Planner在FilterableTableSource的实现不兼容。Old Planner将PlannerExpressions下推到FilterableTableSource而Blink Planner是将Expressions下推到FilterableTableSource
4.基于key-value的字符串配置选项仅仅在Blink Planner支持
5.对CalciteConfig的实现类 PlannerConfig这两组计划实现不同
6.Blink Planner程序将在TableEnvironment和StreamTableEnvironment优化multi-sinks到一个DAG中,但是在Old Planner中总是将每个Sink分离到独立的DAG中,这些DAG彼此之间是独立的
7.Old Planner不支持 Catalog 信息统计,但是Blink支持
Table API & SQL 结构
所有的Table API & SQL 无论是处理batch还是stream都会遵循以下模式,下面一个例子展示代码的常见通用结构:
// 创建TableEnviroment为指定的计划
val tableEnv=...
// 创建一个Table
tableEnv.connect(...).createTemporaryTable("table")
// 从Table API Query中创建Table
val tableAPIResult=tableEnv.from("table").select(...)
val sqlResult=tableEnv.sqlQuery("SELECT ... from table ...")
// 将table的结果输出到TableSink中
val tableResult=tableAPIResult.executeInsert("OutputTable")
TableEnvironment是Table API & SQL中的核心概念,TableEnvironment主要负责:
- 将一个表注册到内部的Catalog中
- 注册catalogs
- 加载可插拔模块
- 执行SQL查询
- 注册用户自定义的function(例如:scalar、table或者aggregation等)
- 将DataStream或者DataSet转换为Table
- 持有ExecutionEnvironment和StreamExecutionEnvironment
每个table总是有指定的TableEnvironment创建并绑定,我们是不可能在同一个查询中联合不同TableEnvironment中的表,比如join或者union等操作.TableEnvironment一般是通过调用BatchTableEnvironment.create()或者
StreamTableEnvironment.create()`的静态方法创建,在调用该方法的时候需要提供ExecutionEnvironment或者StreamExecutionEnvironment参数以及一个可选的TableConfig参数。TableConfig可用于配置TableEnvironment或者用于自定义查询优化和转换过程。
OldPlanner
<!--开发hadoop数据-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.9.2</version>
</dependency>
<!--scala编程环境-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-scala-bridge_2.11</artifactId>
<version>1.10.0</version>
</dependency>
<!--依赖流核心-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_2.11</artifactId>
<version>1.10.0</version>
</dependency>
<!--使用OldPlanner计划-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner_2.11</artifactId>
<version>1.10.0</version>
</dependency>
- 批处理作业
val fbEnv = ExecutionEnvironment.getExecutionEnvironment
val batchTableEnvironment = BatchTableEnvironment.create(fbEnv)
- 流处理作业
val fsSettings = EnvironmentSettings.newInstance().useOldPlanner().inStreamingMode().build()
val fsEnv = StreamExecutionEnvironment.getExecutionEnvironment
val streamTableEnvironment = StreamTableEnvironment.create(fsEnv,fsSettings)
Blink Planner
<!--开发hadoop数据-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.9.2</version>
</dependency>
<!--scala编程环境-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-scala-bridge_2.11</artifactId>
<version>1.10.0</version>
</dependency>
<!--依赖流核心-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_2.11</artifactId>
<version>1.10.0</version>
</dependency>
<!--使用BlinkPlanner计划-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner-blink_2.11</artifactId>
<version>1.10.0</version>
</dependency>
- 批处理作业
var settings=EnvironmentSettings.newInstance.useBlinkPlanner.inBatchMode.build
val fbtEnv = TableEnvironment.create(settings)
- 流处理作业
var settings=EnvironmentSettings.newInstance.useBlinkPlanner.inStreamingMode().build
val bsEnv = StreamExecutionEnvironment.getExecutionEnvironment
val bstEnv = StreamTableEnvironment.create(bsEnv,settings)