Flink SQL的使用

一、Flink SQL简介

Flink SQL是apache Flink中的一种声明式的SQL API,它允许用户已SQL语句的形式对有界(批处理)和无界(流处理)数据进行查询和分析。
中文官网:【https://nightlies.apache.org/flink/flink-docs-release-1.18/zh/docs/dev/】

1.1 Flink SQL 特点

  1. 统一的批流处理:
    Flink SQL对批处理和流处理提供了统一的编程模型。 使用相同的SQL雨具,可以处理静态数据集(批处理)以及实时流入的动态数据(流处理)

  2. 声明式编程:
    用户只需要通过SQL语句描述所需的数据转换和查询逻辑,而无需关心底层的世贤细节。
    比如,要从一个包含用户行为数据的表中筛选出特定时间段内活跃用户的行为记录,只需要用SQL的WHERE子句指定时间范围和活跃用户的条件即可,无需手动编写复杂的代码逻辑来实现数据筛选和处理。

  3. 与标准SQL高度兼容:
    Flink SQL支持大部分标准的SQL语法。
    比如,常见的SELECT、JOIN、GROUP BY等操作在Flink SQL中都有相应的视线,并且语法类似。

  4. 可扩展性:
    Flink SQL可以与FLINK的其他功能模块(如用户自定义函数、连接器等)结合使用,满足复杂的业务需求。
    比如,如果要对数据进行特定的业务逻辑处理,可以自定义一个函数并在FlInk SQL 中调用,同时,可以通过连接器链接到各种数据源(包kafka、hive、JDBC数据源等)进行数据的输入和输出

1.2 工作原理

  1. 解析和验证:
    当用户提交一个Flink SQL查询时,首先会被解析器 解析成 抽象语法树(AST)。然后,验证器 会对AST进行验证,检查语法是否正确以及所引用的表和列是否存在等。

  2. 优化:
    进过验证的查询 会被 优化器 进行优化。优化器会根据查询的特点和数据的分布情况,生成最优的执行计划。

  3. 执行:
    优化后的执行计划会被 转换成 Flink的数据流图(Dataflow Graph),并由Flink的 执行引擎 执行。
    在流处理模式下,数据会持续流入,Flink SQL 会实时处理数据并输出结果;
    在批处理模式下,数据会一次性加载并进行处理;

1.3 应用场景

  1. 实时数据分析:
    在金融领域,实时监控股票交易数据,计算股票价格的移动平均线、涨跌幅等指标;
    在电商领域,实时分析用户的行为数据,如用户点击、购买行为等,一遍及时调整营销策略;

  2. 数据集成
    可以使用Flink SQL从多个数据源(如数据库、消息队列、文件系统等)读取数据,进行清洗、转换 和整合,然后将结果写入到目标数据源中。

  3. ETL(Extract,Transformation,Load)任务
    执行数据抽取、转换和加载任务。 从原始数据源中抽取数据,进行各种数据转换操作(如数据清洗、格式转换、字段计算等),然后将处理后的数据加载到目标存储系统中。
    例如,从日志文件中抽取数据,去除无效记录,转换数据格式,然后加载到数据库中供后续分析使用。

二、Flink SQL语法

2.1 CREATE create语句

根据指定的表名创建一个表,如果同名表存在,则无法创建。

  1. 定义表
    Flink SQL使用CREATE TABLE语句来定义数据源。
CREATE TABLE kafka_table(
	id BIGINT,
	name STRING,
	ts TIMESTAMP(3)WITH (
	'connector' = 'kafka',
	'topic' = 'test_topic',
	'properties.bootstrp.servers' = 'localhost:9092',
	'format' = 'json',
	'scan.startup.mode' ='earliest - offset'
);

定义一个名为mytable的表,包含id(长整型)、name(字符串)、ts(时间戳,进度为毫秒)的三个列。
WITH子句指定了 kafka 连接器的相关属性,包括
connector(连接器类型为kafka)、
topic(读取的kafka主题)、
properties.bootstrp.servers(卡发卡服务器的地址)、
format(数据格式为json)、
scan.startup.mode(从最早的偏移量开始读取)

   CREATE TABLE my_mysql_table (
       id INT,
       name VARCHAR(50),
       age INT
   ) WITH (
       'connector' = 'jdbc',
       'url' = 'jdbc:mysql://localhost:3306/mydatabase',
       'username' = 'your_username',
       'password' = 'your_password',
       'table - name' = 'mytable_in_mysql'
   );

在上述示例中:
connector = ‘jdbc’:指定使用 JDBC Connector 来连接外部数据库。
url:指定了 MySQL 数据库的连接地址。localhost表示本地主机,3306是 MySQL 的默认端口,mydatabase是你要连接的数据库名称。
username和password:是用于登录 MySQL 数据库的用户名和密码。
table - name:是 MySQL 数据库中你要与之交互的表的名称。

  1. 自定义数据源(通过实现接口)
    除了连接常见的数据源,我们还可以自定义数据源。这需要实现TableSource接口。例如,定义一个简单的自定义数据源来生成数字序列
   import org.apache.flink.streaming.api.datastream.DataStream;
   import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
   import org.apache.flink.table.api.DataTypes;
   import org.apache.flink.table.api.TableSchema;
   import org.apache.flink.table.sources.StreamTableSource;
   import java.util.Arrays;
   import java.util.List;
   public class CustomNumberSource implements StreamTableSource<Integer> {
   
       private final List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
       @Override
       public DataStream<Integer> getDataStream(StreamExecutionEnvironment execEnv) {
   
           return execEnv.fromCollection(numbers);
       }
       @Override
       public TableSchema getTableSchema() {
   
           return TableSchema.builder()
                  .field("number", DataTypes.INT())
                  .build();
       }
   }

然后再Flink SQL环境中注册这个定义数据源:

   StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
   EnvironmentSettings settings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build();
   StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env, settings);
   tableEnv.registerTableSource("custom_number_table", new CustomNumberSource());

2.2 SELECT select语句

2.2.1 简单查询

从前面定义的kafka_table中查询id和name 列:
SELECT id,name From kafka_table;

这里返回一个包含id和name的两列数据的结果集

2.2.2 过滤操作

使用where 子句进行过滤,例如 从kafka_name中查询id 大于10且name以“A”开头 的记录
select * from kafka_name where id > 10 and name like ‘A%’;

2.2.3 聚合操作

sum、count、avg、group by等,
比如计算kafka_table中id的总和:select sum(id) from kafka_name;
分组聚合,按name分组计算id的平均值:select name, avg(id) from kafka_name group name;

2.2.4 窗口操作(针对流数据)

对于流数据,窗口操作非常重要。
例如,定义一个滚动窗口来计算每10秒内id的总和:

   SELECT TUMBLE_START(ts, INTERVAL '10' SECOND) as window_start, SUM(id)
   FROM kafka_table
   GROUP BY TUMBLE(ts, INTERVAL '10' SECOND);

这里使用TUMBLE函数来定义滚动窗口,TUMBLE_START函数用于获取窗口的开始时间,对id进行求和操作实在每个10秒的窗口内惊醒的。

2.3 INSERT 语句

插入到另一个表(可以是外部存储)

使用insert into 语句将查询到的结果插入到另一个表中。

例如,将前面查询到的id>10的记录插入到一个名为filtered_table表中

   INSERT INTO filtered_table
       SELECT * FROM kafka_table WHERE id > 10;

2.4 输出到控制台(用于调试)

可以将结果输出到控制台进行调试。
在java代码中,执行查询并将结果转换为DataStream后打印输出:

   Table resultTable = tableEnv.sqlQuery("SELECT * FROM kafka_table WHERE id > 10");
   DataStream<Row> resultStream = tableEnv.toDataStream(resultTable);
   resultStream.print();

三、基础流程

1. 所有Flink的操作都是基于StreamExecutionEnvironment;
2. 
### 使用 Flink SQLFlink CDC 集成 对于希望在 Apache Flink 版本 1.7.1 中使用 Flink SQL 来处理变更数据捕获 (CDC),可以按照如下方法操作。需要注意的是,在此版本中,Flink 社区尚未正式发布官方支持的 CDC 连接器;因此,通常会依赖社区贡献和支持的第三方库来完成这一功能。 #### 启动和停止集群 为了确保环境稳定,在执行任何新的配置之前应当先关闭现有的 Flink 实例并重新启动它: ```bash cd $FLINK_HOME ./bin/stop-cluster.sh ./bin/start-cluster.sh ``` 这一步骤有助于清除可能存在的缓存或临时文件冲突[^1]。 #### 添加必要的依赖项 由于 Flink 1.7.1 默认并不包含用于连接数据库进行 CDC 操作的相关组件,所以需要手动引入这些外部库到项目当中。可以通过 Maven 或 Gradle 构建工具向 `pom.xml` 文件添加相应的依赖声明。例如,对于 TiDB 数据源的支持,可参照特定于该数据库类型的文档说明获取最新兼容版本号,并将其加入构建脚本内。 #### 编写 Flink SQL 查询语句 一旦完成了上述准备工作,则可以在应用程序里编写类似于下面这样的 DDL 定义创建表结构并与目标数据库建立关联关系: ```sql CREATE TABLE my_table ( id BIGINT, name STRING, age INT, ts TIMESTAMP(3), WATERMARK FOR ts AS ts - INTERVAL '5' SECOND -- 设置水印延迟时间 ) WITH ( 'connector.type' = 'jdbc', -- 表明这是一个 JDBC 类型的数据源 'connector.url' = 'jdbc:mysql://...', -- 替换成实际 MySQL/TiDB URL 地址 'connector.table' = 'my_source_table', 'connector.driver' = 'com.mysql.jdbc.Driver', 'format' = 'json' ); ``` 请注意以上示例中的参数设置需依据所使用的具体数据库类型调整相应属性值。此外,关于如何定义更复杂的逻辑以及利用 Debezium 等框架实现真正的 CDC 功能,请参阅相关项目的官方指南以获得详细的指导信息。 #### 提交作业至 Flink Cluster 最后通过命令行提交编写的 SQL 脚本给正在运行的服务端节点即可开始处理来自上游系统的增量更新事件流。 ```bash $FLINK_HOME/bin/flink run \ -jarfile path/to/my-flink-job.jar \ -c com.example.MyMainClass \ --table-dml-sync true \ --parallelism 1 ``` 这里假设已经打包好了一个包含所有必要类路径资源的应用程序 JAR 包,并指定了入口点作为主函数所在的位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超人在良家-阿启

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值