flink sql
数据类型:
-- 字符串类型 # char类型 CHAR CHAR(n) -- n在 1 和 2147483647 之间 未设置n=1 # 字符串类型 VARCHAR VARCHAR(n) -- n在 1 和 2147483647 之间 未设置n=1 STRING -- 等于最大的varchar(max) # 二进制类型 BINARY BINARY(n) -- 范围同上 # 可变长度二进制类型 VARBINARY VARBINARY(n) -- 类似于string BYTES -- 数字类型 # 带有精度的十进制数字类型 -- 类似于java中的 DECIMAL DECIMAL(p) DECIMAL(p, s) DEC DEC(p) DEC(p, s) NUMERIC NUMERIC(p) NUMERIC(p, s) # 带符号 TINYINT -- -128 to 127 SMALLINT -- -32768 to 32767 # 不带符号的 INT -- 2147483,648 to 2147483647 INTEGER BIGINT -- -9223372036854775808 to 9223372036854775807 # 带小数的 FLOAT DOUBLE -- 时间类型 #日期 DATE -- 2020-10-12 #时间 TIME TIME(p) -- 10:10:12.p 不指定p,p= 0 #时间戳 TIMESTAMP TIMESTAMP(p) -- 2020-12-12 12:10:11.p -- 其他类型 # ARRAY<t> t ARRAY #map类型 MAP<kt, vt>
DDL
建表,表分为两种:
- 临时表:通常保存于内存中并且仅在创建它们的 Flink session(可以理解为一次 Flink 任务的运行)持续期间存在。这些表对于其它 session(即其他 Flink 任务或非此次运行的 Flink 任务)是不可见的。因为这个表的元数据没有被持久化。如下案例:
-- 临时外部表
CREATE TEMPORARY TABLE source_table (
user_id BIGINT,
`name` STRING
) WITH (
'connector' = 'user_defined',
'format' = 'json',
'class.name' = 'flink.examples.sql._03.source_sink.table.user_defined.UserDefinedSource'
);
- 永久表:需要外部 Catalog(例如 Hive Metastore)来持久化表的元数据。一旦永久表被创建,它将对任何连接到这个 Catalog 的 Flink session 可见且持续存在,直至从 Catalog 中被明确删除。如下案例:
-- 永久外部表。需要外部 Catalog 持久化!!!
CREATE TABLE source_table (
user_id BIGINT,
`name` STRING
) WITH (
'connector' = 'user_defined',
'format' = 'json',
'class.name' = 'flink.examples.sql._03.source_sink.table.user_defined.UserDefinedSource'
);
使用场景:
使用场景
临时表适用场景
-
临时数据分析:当需要临时处理一些中间数据,且不希望影响其他会话时
-
测试和调试:快速创建表结构进行SQL验证,无需持久化
-
会话级中间结果:在复杂查询中作为中间步骤的存储
-
个性化视图:为特定会话创建个性化数据视图
永久表适用场景
-
持久化数据存储:需要长期保存的表结构和数据
-
跨会话共享:多个Flink作业或会话需要访问相同表定义
-
生产环境应用:作为正式数据管道的一部分
-
与外部系统集成:需要Hive等其他系统访问的表定义
不同的数据源对应不同的连接器,可以通过官方文档查询连接器以及对应的参数。
阿里云连接器文档:https://help.aliyun.com/zh/flink/developer-reference/supported-connectors?spm=a2c4g.11186623.help-menu-45029.d_5_0_0.69cefa0c8wipPU
DQL
常用函数可以参考flink官方文档:
https://nightlies.apache.org/flink/flink-docs-release-1.13/docs/dev/table/functions/systemfunctions/
如果用的是flink官网阿里版,看阿里云的文档即可:
https://help.aliyun.com/zh/flink/developer-reference/overview-7?spm=a2c4g.11174283.help-menu-45029.d_5_2_6_0.2ede2215EXpjic&scm=20140722.H_188424._.OR_help-T_cn~zh-V_1
1.with子句
和ODPS SQL一样使用
2.select和where
和标准SQL一样使用
3.select和distinct
和离线不同,实时的去重需要保留状态,那么要么设置状态时间
state.ttl,或者根据实际情况,通过窗口和group by 去重
4.窗口表值函数TVF
核心是windows,将无限的流分为有限的流:
窗口函数分位滚动、滑动、累计窗口:TUMBLE
、HOP
和CUMULATE
示例数据源:
-- 创建Kafka源表 CREATE TABLE user_events ( user_id BIGINT, item_id BIGINT, category_id BIGINT, behavior STRING, event_time TIMESTAMP(3), -- 定义事件时间属性 WATERMARK FOR event_time AS event_time - INTERVAL '5' SECOND ) WITH ( 'connector' = 'kafka', 'topic' = 'user_events', 'properties.bootstrap.servers' = 'kafka:9092', 'properties.group.id' = 'user_behavior', 'scan.startup.mode' = 'latest-offset', 'format' = 'json' );
滚动窗口:
TUMBLE(TABLE data, DESCRIPTOR(timecol), size [, offset ])
返回值:
UMBLE 的返回值是一个新的关系,它包括原来表的所有列以及另外3列“window_start”,“window_end”,“window_time”来表示分配的窗口。
用于计算窗口的表,必须有时间戳字段
-- 计算每5分钟各商品的点击量 CREATE TABLE item_click_counts_5min ( window_start TIMESTAMP(3), window_end TIMESTAMP(3), item_id BIGINT, click_count BIGINT, -- 添加处理时间,便于下游消费 proc_time AS PROCTIME() ) WITH ( 'connector' = 'kafka', 'topic' = 'item_click_counts_5min', 'properties.bootstrap.servers' = 'kafka:9092', 'format' = 'json', 'json.ignore-null-fields' = 'false' ); -- 将窗口计算结果插入到输出表 INSERT INTO item_click_counts_5min SELECT window_start, window_end, item_id, COUNT(*) AS click_count FROM TABLE( TUMBLE(TABLE user_events, DESCRIPTOR(event_time), INTERVAL '5' MINUTES) ) WHERE behavior = 'click' GROUP BY window_start, window_end, item_id;
滑动窗口类似用法:
-- 创建UV结果表(输出到MySQL) CREATE TABLE user_activity_uv ( window_start TIMESTAMP(3), window_end TIMESTAMP(3), uv BIGINT, PRIMARY KEY (window_start, window_end) NOT ENFORCED ) WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://mysql:3306/analytics', 'table-name' = 'user_activity_uv', 'username' = 'flink', 'password' = 'flinkpw', 'sink.buffer-flush.interval' = '1s' ); -- 计算滑动窗口UV并写入MySQL INSERT INTO user_activity_uv SELECT window_start, window_end, COUNT(DISTINCT user_id) AS uv FROM TABLE( HOP(TABLE user_events, DESCRIPTOR(event_time), INTERVAL '1' MINUTES, INTERVAL '10' MINUTES) ) GROUP BY window_start, window_end;
DML