TableAPI
Apache Flink 的 Table API 是一个统一的关系式 API,适用于流处理和批处理。它提供了一种高级别的、声明式的方式来处理数据流和批量数据,使得数据处理变得更加直观和简洁。Table API 和 SQL API 紧密集成,可以相互转换,提供了强大的灵活性和功能。
Table API 的主要特性
统一的批处理和流处理
- Table API 支持批处理和流处理,可以对动态数据流和静态数据集使用相同的 API。
声明式查询
- 用户可以使用类似 SQL 的语法编写查询,而不需要关注底层的执行细节。
多种数据源和目标
- 支持多种数据源和数据汇,包括 Kafka、文件系统、JDBC、Elasticsearch 等。
与 SQL 集成
- 可以在 Table API 中使用 SQL 查询,或者将 Table API 查询结果转换为 SQL 查询。
基本使用流程
设置执行环境
- 创建 StreamExecutionEnvironment 或 ExecutionEnvironment 作为基础环境。
- 创建 StreamTableEnvironment 或 TableEnvironment 进行 Table API 操作。
定义表
- 通过连接器定义源表和目标表。
编写查询
- 使用 Table API 编写查询,包括过滤、选择、聚合、连接等操作。
执行查询
- 将查询结果写入目标表,或者直接触发查询执行。
示例代码
以下是一个基本的 Flink Table API 示例,包括设置环境、定义表和执行查询。
// 设置执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);
// 定义 Kafka 源表
String sourceDDL = "CREATE TABLE kafka_source ("
+ " user_id STRING,"
+ " action STRING,"
+ " timestamp TIMESTAMP(3),"
+ " WATERMARK FOR timestamp AS timestamp - INTERVAL '5' SECOND"
+ ") WITH ("
+ " 'connector' = 'kafka',"
+ " 'topic' = 'input_topic',"
+ " 'properties.bootstrap.servers' = 'localhost:9092',"
+ " 'format' = 'json'"
+ ")";
tableEnv.executeSql(sourceDDL);
// 定义 Kafka 目标表
String sinkDDL = "CREATE TABLE kafka_sink ("
+ " user_id STRING,"
+ " action STRING,"
+ " action_count BIGINT,"
+ " window_start TIMESTAMP(3),"
+ " window_end TIMESTAMP(3)"
+ ") WITH ("
+ " 'connector' = 'kafka',"
+ " 'topic' = 'output_topic',"
+ " 'properties.bootstrap.servers' = 'localhost:9092',"
+ " 'format' = 'json'"
+ ")";
tableEnv.executeSql(sinkDDL);
// 使用 Table API 进行查询
Table result = tableEnv
.from("kafka_source")
.window(Tumble.over(lit(10).minutes()).on($("timestamp")).as("w"))
.groupBy($("w"), $("user_id"))
.select(
$("user_id"),
$("action"),
$("w").start().as("window_start"),
$("w").end().as("window_end"),
$("action").count().as("action_count")
);
// 将查询结果写入目标表
result.executeInsert("kafka_sink");
Table API 常用操作
选择(Select)
Table result = tableEnv.from("kafka_source")
.select($("user_id"), $("action"), $("timestamp"));
过滤(Filter)
Table filtered = tableEnv.from("kafka_source")
.filter($("action").isEqual("purchase"));
聚合(Aggregation)
Table aggregated = tableEnv.from("kafka_source")
.groupBy($("user_id"))
.select($("user_id"), $("action").count().as("action_count"));
连接(Join)
Table joined = tableEnv.from("kafka_source")
.join(tableEnv.from("another_table"))
.where($("kafka_source.user_id").isEqual($("another_table.user_id")))
.select($("kafka_source.user_id"), $("kafka_source.action"), $("another_table.info"));
窗口操作(Windowing)
Table windowed = tableEnv.from("kafka_source")
.window(Tumble.over(lit(10).minutes()).on($("timestamp")).as("w"))
.groupBy($("w"), $("user_id"))
.select($("user_id"), $("w").start().as("window_start"), $("w").end().as("window_end"), $("action").count().as("action_count"));
总结
Flink 的 Table API 提供了一种声明式的、类似 SQL 的方式来进行数据流和批处理。它使用户能够使用高层次的查询语言进行数据处理,而不需要关心底层的实现细节。通过与 SQL 的紧密集成,Table API 既保留了 SQL 的易用性,又提供了更强大的编程灵活性,是构建 Flink 应用的强大工具。
使用Table API调用完整的分析SQL
使用 Flink 的 Table API 可以调用和执行完整的 Flink SQL 查询。Flink 提供了将 SQL 查询嵌入到 Table API 中的方法,使得用户可以在程序中编写和执行 SQL 语句。
下面是一个完整的示例,演示如何使用 Table API 调用和执行从 Kafka 读取数据、进行分析并将结果写回 Kafka 的 Flink SQL 查询。
步骤:
- 设置执行环境。
- 定义 Kafka 源表和目标表。
- 编写和执行 SQL 查询。
- 将结果写入目标表。
示例代码:
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.api.*;
import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
public class FlinkSqlExample {
public static void main(String[] args) {
// 设置执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);
// 定义 Kafka 源表
String sourceDDL = "CREATE TABLE kafka_source ("
+ " user_id STRING,"
+ " action STRING,"
+ " timestamp TIMESTAMP(3),"
+ " WATERMARK FOR timestamp AS timestamp - INTERVAL '5' SECOND"
+ ") WITH ("
+ " 'connector' = 'kafka',"
+ " 'topic' = 'input_topic',"
+ " 'properties.bootstrap.servers' = 'localhost:9092',"
+ " 'format' = 'json'"
+ ")";
tableEnv.executeSql(sourceDDL);
// 定义 Kafka 目标表
String sinkDDL = "CREATE TABLE kafka_sink ("
+ " user_id STRING,"
+ " action_count BIGINT,"
+ " window_start TIMESTAMP(3),"
+ " window_end TIMESTAMP(3)"
+ ") WITH ("
+ " 'connector' = 'kafka',"
+ " 'topic' = 'output_topic',"
+ " 'properties.bootstrap.servers' = 'localhost:9092',"
+ " 'format' = 'json'"
+ ")";
tableEnv.executeSql(sinkDDL);
// 编写 SQL 查询
String query = "INSERT INTO kafka_sink "
+ "SELECT "
+ " user_id, "
+ " COUNT(action) AS action_count, "
+ " TUMBLE_START(timestamp, INTERVAL '10' MINUTE) AS window_start, "
+ " TUMBLE_END(timestamp, INTERVAL '10' MINUTE) AS window_end "
+ "FROM kafka_source "
+ "GROUP BY "
+ " user_id, "
+ " TUMBLE(timestamp, INTERVAL '10' MINUTE)";
// 执行 SQL 查询
tableEnv.executeSql(query);
}
}
详细说明:
设置执行环境
- 创建 StreamExecutionEnvironment 和 StreamTableEnvironment,用于流处理和 Table API 操作。
定义 Kafka 源表
- 使用 CREATE TABLE 语句定义源表 kafka_source,指定数据的字段和数据源的连接配置。
定义 Kafka 目标表
- 使用 CREATE TABLE 语句定义目标表 kafka_sink,指定数据的字段和数据汇的连接配置。
编写 SQL 查询
- 编写一个 SQL 查询,将源表的数据进行窗口聚合,计算每个用户在10分钟窗口内的操作次数。
执行 SQL 查询
- 使用 tableEnv.executeSql(query) 执行 SQL 查询,将结果写入目标表。
总结
通过使用 Flink 的 Table API,可以在 Java 程序中嵌入和执行完整的 Flink SQL 查询。这种方式结合了 SQL 的声明式编程和 Table API 的灵活性,使得开发复杂的流处理和批处理应用变得更加简洁和高效。
Table API的应用
目前市面上很多基于 Flink SQL 的在线编辑和任务执行引擎主要是通过 Flink 的 Table API 实现的。通过 Table API,用户可以在运行时动态地解析和执行 SQL 查询。这种方法提供了灵活性和高效性,使得在交互式环境中执行流式和批处理查询变得非常方便。
基于 Table API 实现的在线编辑任务执行引擎
Flink 的 Table API 是一个高级别的 API,可以轻松地将 SQL 查询转换为 Flink 程序,并且在执行环境中运行这些程序。这使得许多在线 SQL 编辑器和执行引擎可以动态地接受用户输入的 SQL 查询,并将其转换为 Flink 的作业进行执行。
其他方法
除了使用 Table API,还有其他几种方法可以实现基于 Flink SQL 的在线编辑任务执行:
直接使用 SQL API
- Flink 的 SQL API 允许直接编写 SQL 查询,并在执行环境中运行这些查询。SQL API 和 Table API 是紧密集成的,很多情况下是可以互换使用的。
Flink SQL CLI
- Flink 提供了一个命令行工具(SQL CLI),可以用于交互式地执行 SQL 查询。这适用于需要手动输入 SQL 并立即查看结果的场景。
REST API
- 使用 Flink 提供的 REST API,可以将 SQL 查询提交到 Flink 集群进行执行。通过自定义的 Web 界面或应用程序,用户可以在线编辑和提交 SQL 查询到 Flink 集群。
- 自定义的 REST 服务可以解析用户输入的 SQL,调用 Flink 的 REST API 提交作业,并将结果返回给用户。
Flink Dashboard
- Flink 的 Web Dashboard 提供了一些交互式功能,可以查看和管理作业状态。虽然不直接支持 SQL 编辑和执行,但可以集成其他工具以实现此功能。
Flink SQL Gateway
- Flink SQL Gateway 是一个面向 SQL 的接口层,允许用户通过 JDBC 或 REST API 提交 SQL 查询。SQL Gateway 可以作为一个中间层,解析用户的 SQL 查询,并将其转换为 Flink 作业进行执行。
示例:使用 REST API 提交 SQL 查询
假设我们有一个自定义的 Web 应用,用户可以在界面上输入 SQL 查询,并提交到 Flink 集群执行。以下是一个简单的 REST 服务示例,展示如何通过 REST API 提交 SQL 查询:
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/flink-sql")
public class FlinkSqlController {
@Autowired
private RestTemplate restTemplate;
@PostMapping("/execute")
public ResponseEntity<String> executeSql(@RequestBody String sqlQuery) {
String flinkUrl = "http://localhost:8081/v1/sql/execute";
Map<String, String> request = new HashMap<>();
request.put("statement", sqlQuery);
ResponseEntity<String> response = restTemplate.postForEntity(flinkUrl, request, String.class);
return ResponseEntity.ok(response.getBody());
}
}
在这个示例中,我们创建了一个简单的 Spring Boot REST 服务,允许用户通过 POST 请求提交 SQL 查询,并将其转发到 Flink 集群进行执行。
总结
虽然大多数基于 Flink SQL 的在线编辑和任务执行引擎都是通过 Table API 实现的,但还有其他方法可以实现类似的功能,包括直接使用 SQL API、Flink SQL CLI、REST API、Flink Dashboard 和 Flink SQL Gateway 等。这些方法各有优劣,可以根据具体需求选择合适的方案。