Flink 系列第20篇:Flink SQL 语法全解:从 DDL 到 DML,窗口、聚合、列转行一网打尽

32.flink sql 语法大全 flink table api 之 time Attributes, which supports standard ANSI SQL(ANSI SQL是sql语言标准).Calcite 是什么?如果用一句话形容 Calcite,Calcite 是一个用于优化异构数据源的查询处理的基础框架。最近十几年来,出现了很多专门的数据处理引擎。例如列式存储 (HBase)、流处理引擎 (Flink)、文档搜索引擎 (Elasticsearch) 等等。 阅读详情

一、DDL:构建你的数据世界

在 Flink SQL 中,一切计算的起点都是 CREATE 语句。它负责向当前或指定的 Catalog 中注册库、表、视图或函数。你可以像在传统数据库中一样,使用 CREATE DATABASE、CREATE TABLE、CREATE VIEW 和 CREATE FUNCTION 来搭建自己的元数据体系。

1.1 创建表:CREATE TABLE

建表语句是连接外部系统并定义表结构的核心手段。如果同名表已经在 Catalog 中存在,则无法注册,除非使用 IF NOT EXISTS。

1.1.1 建表语法骨架
CREATE TABLE [IF NOT EXISTS] [catalog_name.][db_name.]table_name
  (
    { <physical_column_definition> |   -- 物理列
      <metadata_column_definition> |   -- 元数据列
      <computed_column_definition>     -- 计算列
    }[ , ...n]
    [ <watermark_definition> ]         -- Watermark
    [ <table_constraint> ][ , ...n]    -- 约束
  )
  [COMMENT table_comment]
  [PARTITIONED BY (partition_column_name1, partition_column_name2, ...)]
  WITH (key1=val1, key2=val2, ...)
  [ LIKE source_table [( <like_options> )] ]

仔细拆解,这个框架包含了 Flink 表定义的几乎所有能力:

  • 物理列:实际存储在外部系统中的字段。
  • 元数据列:从连接器自身元数据中提取的虚拟字段,如 Kafka 的 offset、timestamp。
  • 计算列:基于其他列或常量通过表达式计算出的虚拟列,常用于定义时间属性。
  • Watermark:为事件时间提供进度指示。
  • 约束:目前主要支持 PRIMARY KEY,但 NOT ENFORCED 表示 Flink 不校验唯一性,仅用于优化器和连接器的语义推导。
  • WITH 子句:连接外部系统时的配置参数。
  • LIKE 子句:基于已有表的 Schema 创建新表,支持灵活地包含或排除约束、分区、生成列、Watermark 等。
1.1.2 三种列类型详解

物理列 是最常见的列,定义了介质中实际存储字段的名称和类型。语法格式为:

column_name column_type [ <column_constraint> ] [COMMENT column_comment]

元数据列 通过 METADATA 关键字标识,允许你直接读取数据源自带的元信息。例如,从 Kafka 中读取消息的偏移量和写入时间戳:

CREATE TABLE kafka_source (
  user_id BIGINT,
  message STRING,
  offset BIGINT METADATA FROM 'offset' VIRTUAL,   -- 只读虚拟列,不写入Sink
  ts TIMESTAMP(3) METADATA FROM 'timestamp'        -- 可写元数据列
) WITH (
  'connector' = 'kafka',
  ...
);
  • FROM metadata_key:指定连接器提供的元数据键,如果自定义列名与元数据键相同,则 FROM 可省略。
  • VIRTUAL 关键字表示该列为纯逻辑字段,不会物化到 Sink 中,常用于条件过滤或时间提取。如果不带 VIRTUAL,则默认是可读可写的,会被输出到外部系统(前提是 Sink 支持)。为增强可读性,建议在可写时显式声明 NOT VIRTUAL。

注意:某些元数据天生只读,例如 Kafka 的 offset 就不能被写入,否则会报错。

计算列 是一个虚拟列,定义时使用 AS 加表达式。它可以包含其他列、常量、函数,但不能写子查询。计算列最常见的用途就是定义时间属性,比如将字符串或长整型时间戳转换为 TIMESTAMP_LTZ:

CREATE TABLE events (
  ts_ms BIGINT,
  ts AS TO_TIMESTAMP_LTZ(ts_ms, 3),
  WATERMARK FOR ts AS ts - INTERVAL '5' SECOND
);
1.1.3 Watermark 定义:事件时间的节拍器

只有定义了 Watermark,Flink 才知道事件时间字段如何推进。语法为:

WATERMARK FOR rowtime_column_name AS watermark_strategy_expression
  • rowtime_column_name 必须为 TIMESTAMP(3) 或 TIMESTAMP_LTZ(3) 类型。
  • watermark_strategy_expression 通常是 rowtime_column_name - INTERVAL 'max_delay'。

Flink SQL 提供了三种内置的 Watermark 生成策略:

  1. 有界无序(最常用):WATERMARK FOR ts AS ts - INTERVAL '5' SECOND,允许 5 秒的最大乱序。
  2. 严格升序(几乎不用):WATERMARK FOR ts AS ts,假设时间戳严格递增,一旦出现相等或更小值就视为迟到。
  3. 递增(一般不用):WATERMARK FOR ts AS ts - INTERVAL '0.001' SECOND,允许相同时间戳但不允许更小。

Watermark 的发出间隔可通过参数 pipeline.auto-watermark-interval 控制,默认 200ms。

1.1.4 主键约束
PRIMARY KEY (column_name[, ...]) NOT ENFORCED
  • 主要用于 Upsert 型连接器(如 JDBC、Elasticsearch),让 Flink 知道哪些字段可唯一标识一行。
  • NOT ENFORCED 意味着 Flink 不会去校验数据的唯一性,仅仅作为元数据传递给优化器和 Sink。
  • 主键列不允许为 NULL。
1.1.5 WITH 子句参数

WITH 子句以键值对的形式定义连接器及其属性,是连接外部系统的“万能接口”。

参数说明示例
connector连接器类型'kafka', 'jdbc', 'filesystem'
format数据格式'json', 'csv', 'avro'
scan.startup.mode源表消费起始模式'earliest-offset', 'latest-offset'
sink.parallelismSink 并行度'2'
update-mode更新模式'append', 'upsert'

各连接器具体的参数请参考 Flink 官方文档的 Connectors 部分。

1.1.6 分区表与 LIKE 子句

Flink 支持类似 Hive 的分区表,主要用于批处理场景,配合文件系统或 Hive 连接器使用:

CREATE TABLE partitioned_table (
  user_id BIGINT,
  event STRING
) PARTITIONED BY (dt STRING, hr STRING)
WITH (
  'connector' = 'filesystem',
  'path' = '/data/events',
  'format' = 'parquet'
);

CREATE TABLE ... LIKE 可以方便地复制表定义,并灵活选择继承哪些特性:

CREATE TABLE kafka_backup LIKE kafka_source (
  EXCLUDING OPTIONS    -- 不复制原表的连接配置
) WITH (
  'connector' = 'kafka',
  'topic' = 'backup_topic',
  ...
);

INCLUDING / EXCLUDING / OVERWRITING 可控制对 CONSTRAINTS、PARTITIONS、GENERATED(计算列)、OPTIONS、WATERMARKS 等属性的处理。

1.2 创建数据库、视图与函数

数据库:CREATE DATABASE [IF NOT EXISTS] [catalog_name.]db_name [COMMENT ...] WITH (key=val, ...),用于逻辑分组。

视图:CREATE [TEMPORARY] VIEW [IF NOT EXISTS] view_name AS query_expression。视图是逻辑上的查询封装,不存储数据,可用于简化复杂查询。

函数:CREATE [TEMPORARY|TEMPORARY SYSTEM] FUNCTION function_name AS identifier [LANGUAGE JAVA|SCALA|PYTHON]。支持加载 UDF,方便扩展业务逻辑。

1.3 修改与删除

常用的修改删除语句包括:

ALTER TABLE my_table RENAME TO new_table_name;
DROP TABLE IF EXISTS my_table;
DROP VIEW my_view;
DROP DATABASE my_db;

这些语句与标准 SQL 基本一致。


二、DML:流式查询的艺术

2.1 WITH 语句:给复杂查询起个别名

WITH 子句(CTE,Common Table Expression)允许在查询中定义临时结果集,极大地提升了复杂 SQL 的可读性和维护性。语法如下:

WITH [RECURSIVE] cte_name [ (column_name [, ...]) ] AS (
  subquery
)
[, ...]
main_query

多 CTE 串联是最常见的用法,例如先定义高价值用户,再关联订单:

WITH 
  high_value_users AS (
    SELECT user_id FROM users WHERE credit_score > 800
  ),
  hv_user_orders AS (
    SELECT o.*
    FROM orders o
    JOIN high_value_users hvu ON o.user_id = hvu.user_id
  )
SELECT 
    COUNT(*) AS high_value_orders,
    SUM(amount) AS total_amount
FROM hv_user_orders;

Flink 1.16+ 支持递归 CTE,非常适合处理树形或层次结构数据:

WITH RECURSIVE employee_hierarchy AS (
    -- 锚点成员:顶级管理者
    SELECT id, name, manager_id, 1 AS level
    FROM employees WHERE manager_id IS NULL
    UNION ALL
    -- 递归成员:下属
    SELECT e.id, e.name, e.manager_id, eh.level + 1
    FROM employees e
    JOIN employee_hierarchy eh ON e.manager_id = eh.id
)
SELECT * FROM employee_hierarchy;

注意:递归 CTE 必须有终止条件,否则会无限递归;过深的嵌套可能影响可读性;CTE 的作用域仅限于当前查询。

2.2 SELECT 与 DISTINCT 的流式语义

标准 SELECT 骨架如下:

SELECT [DISTINCT] select_list
FROM table_expression
[ WHERE boolean_expression ]
[ GROUP BY grouping_expression ]
[ HAVING boolean_expression ]
[ ORDER BY order_expression ]

在无界流上,ORDER BY 需要配合 LIMIT 使用,因为无限流无法对所有数据进行全局排序。

SELECT DISTINCT 在流式任务中隐藏着状态陷阱。我们来看一个例子:

INSERT INTO target_table
SELECT DISTINCT id FROM Orders;

这段 SQL 的背后实际经历了:

  1. Source 算子:从 Kafka 持续读取数据,逐条发给下游去重算子。
  2. 去重算子:维护一个状态,记录已经见过的 id。如果新来的 id 不在状态中,则将其加入状态并输出;如果已存在,则丢弃。
  3. Sink 算子:将去重后的数据写入目标表。

关键点在于,状态会随着不同 id 的数量而无限制增长。为了防止 OOM,可以为状态设置 TTL(存活时间),但这也可能导致长周期后再次出现的 id 被重复输出,破坏去重语义。因此,在实时去重场景中,需要权衡数据完整性与资源消耗。

2.3 时间窗口:用 TVF 玩转四种窗口

Flink SQL 提供了四种时间窗口:滚动窗口(TUMBLE)、滑动窗口(HOP)、会话窗口(SESSION) 和 累积窗口(CUMULATE)。从 1.13 版本开始,推荐使用窗口表值函数(Window TVF) 来定义窗口,语法更清晰,并且与标准 SQL 的 GROUP BY 更协调。老式的 GROUP BY TUMBLE(row_time, interval '1' MINUTE) 写法已被标记为废弃。

2.3.1 窗口 TVF 通用语法
SELECT col1, agg_func(col2), window_start, window_end
FROM TABLE(窗口函数名(
    TABLE 数据源表,
    DESCRIPTOR(时间列),
    窗口大小参数,
    [其他参数]
))
GROUP BY window_start, window_end, col1;

窗口 TVF 会自动生成三个元数据列:

  • window_start:窗口起始时间(含),类型 TIMESTAMP(3)。
  • window_end:窗口结束时间(不含),类型 TIMESTAMP(3)。
  • window_time:窗口内最大有效时间戳,等于 window_end - 1 毫秒,类型 TIMESTAMP_LTZ(3)。它的核心用途是时态表关联(Temporal Join),确保关联到窗口关闭之前的维表版本,避免拿错下一窗口的数据。

GROUP BY 子句必须包含至少一个窗口元数据字段(通常是 window_start 和 window_end)以及业务分组键。

2.3.2 滚动窗口(TUMBLE)

固定大小,不重叠。每条数据只属于一个窗口。

-- 数据源表
CREATE TABLE source_table (
    dim STRING,
    user_id BIGINT,
    price BIGINT,
    row_time AS CAST(CURRENT_TIMESTAMP AS TIMESTAMP(3)),
    WATERMARK FOR row_time AS row_time - INTERVAL '5' SECOND
) WITH (...);

-- 聚合查询
INSERT INTO sink_table
SELECT 
    dim,
    UNIX_TIMESTAMP(CAST(window_start AS STRING)) * 1000 AS window_start,
    COUNT(*) AS pv,
    SUM(price) AS sum_price,
    MAX(price) AS max_price,
    MIN(price) AS min_price,
    COUNT(DISTINCT user_id) AS uv
FROM TABLE(TUMBLE(
    TABLE source_table,
    DESCRIPTOR(row_time),
    INTERVAL '60' SECOND
))
GROUP BY window_start, window_end, dim;

流式语义分析:

  • Source 逐条发送数据给窗口聚合算子。
  • 窗口算子根据事件时间(或处理时间)将数据分配到对应窗口。
  • 对于事件时间,当收到的 Watermark > 窗口结束时间 时,窗口触发计算并输出结果。后续的迟到数据默认会被丢弃。
  • Sink 将计算结果写出。
2.3.3 滑动窗口(HOP)

窗口有大小和滑动步长,若步长 < 窗口大小则窗口重叠,一条数据会落入多个窗口。

-- 数据源定义同上,聚合如下:
SELECT 
    dim,
    COUNT(DISTINCT user_id) AS uv
FROM TABLE(HOP(
    TABLE source_table,
    DESCRIPTOR(row_time),
    INTERVAL '1' MINUTES,   -- 滑动步长
    INTERVAL '5' MINUTES    -- 窗口大小
))
GROUP BY window_start, window_end, dim;
2.3.4 会话窗口(SESSION)

没有固定时长,由“会话超时时间”界定。若在 INTERVAL 内没有新数据到达,窗口就关闭。

SELECT
  window_start, window_end, user_id,
  COUNT(*) AS events_count
FROM TABLE(SESSION(
    TABLE user_activity,
    DESCRIPTOR(activity_time),
    INTERVAL '30' MINUTES   -- 会话超时
))
GROUP BY window_start, window_end, user_id;
2.3.5 累积窗口(CUMULATE)

它以一个最大窗口为周期,按固定步长“逐步扩张”。例如,步长 5 分钟,最大窗口 15 分钟,则从 00:00 开始会依次产生:
[00:00,00:05)、[00:00,00:10)、[00:00,00:15) 三个窗口。

SELECT 
    window_start, window_end,
    SUM(money) AS sum_money,
    COUNT(DISTINCT user_id) AS uv
FROM TABLE(CUMULATE(
    TABLE source_table,
    DESCRIPTOR(row_time),
    INTERVAL '60' SECOND,   -- 累积步长
    INTERVAL '1' DAY        -- 最大窗口大小
))
GROUP BY window_start, window_end;

累积窗口特别适合“每日零点累计到当前时刻”的统计,例如当日累计销售额、实时大屏等场景。

2.3.6 TVF 与多维分析:Grouping Sets / Rollup / Cube

Window TVF 支持在窗口聚合中直接使用 GROUPING SETS、ROLLUP 和 CUBE,实现一次查询输出多个维度组合的窗口统计。

SELECT
    window_end,
    IF(age IS NULL, 'ALL', age) AS age,
    IF(sex IS NULL, 'ALL', sex) AS sex,
    COUNT(DISTINCT user_id) AS uv
FROM TABLE(CUMULATE(
    TABLE source_table,
    DESCRIPTOR(row_time),
    INTERVAL '5' SECOND,
    INTERVAL '1' DAY
))
GROUP BY window_start, window_end,
    GROUPING SETS (
        (),
        (age),
        (sex),
        (age, sex)
    );

2.4 Group By 聚合:没有窗口的“窗口”

脱离时间窗口,普通的 GROUP BY 在流处理中也极有用,但它的语义与窗口聚合截然不同。

窗口聚合 vs Group By 聚合的核心差异:

  • 触发机制:窗口聚合由 Watermark(事件时间)或系统时钟(处理时间)驱动,结果输出后即为最终值;Group By 聚合由数据到达驱动,来一条数据就立刻计算并输出。
  • 结果持续性:窗口聚合结果确定后不再变化;Group By 聚合是持续更新的,新数据到来会使旧结果失效,因此会产生撤回流(Retract)。
  • 语义一致性:窗口聚合适用于具有时间边界的历史统计;Group By 聚合适合持续维护最新的汇总状态。

举例:用滚动窗口和 Group By 实现每分钟 PV/UV 的比较。

-- 滚动窗口聚合
INSERT INTO sink_table
SELECT 
    dim,
    COUNT(*) AS pv,
    COUNT(DISTINCT user_id) AS uv,
    UNIX_TIMESTAMP(CAST(TUMBLE_START(row_time, INTERVAL '1' MINUTE) AS STRING)) * 1000 AS window_start
FROM source_table
GROUP BY dim, TUMBLE(row_time, INTERVAL '1' MINUTE);

-- 普通 Group By 聚合(手动将时间对齐到分钟)
INSERT INTO sink_table
SELECT
    dim,
    COUNT(*) AS pv,
    COUNT(DISTINCT user_id) AS uv,
    CAST((UNIX_TIMESTAMP(CAST(row_time AS STRING))) / 60 AS BIGINT) AS window_start
FROM source_table
GROUP BY dim, CAST((UNIX_TIMESTAMP(CAST(row_time AS STRING))) / 60 AS BIGINT);

离线场景两者结果可以等价;但在流式处理中,窗口聚合输出的是不可变的追加流,而 Group By 聚合输出的是可变的撤回流。

撤回流(Retract Stream) 的流程:

  1. Source 将数据按 GROUP BY key 的哈希发给下游聚合算子。
  2. 聚合算子到 State 中查找该 key 的历史聚合结果。
    • 若存在旧值:计算新值,更新 State,先下发 - [key, oldValue] 撤回旧结果,再下发 + [key, newValue]。
    • 若不存在:直接计算新值并更新 State,下发 + [key, newValue]。
  3. Sink 接收到撤回流,需要在支持撤回的存储(如 Kafka 的 upsert 模式或数据库)中执行更新或删除。

Group By 的状态同样会无限增长,务必设置合理 TTL。

与 TVF 类似,普通的 Group By 也支持 GROUPING SETS、ROLLUP 和 CUBE,例如:

SELECT 
    supplier_id, rating, product_id, COUNT(*)
FROM Products
GROUP BY GROUPING SETS (
    (supplier_id, product_id, rating),
    (supplier_id, product_id),
    (supplier_id),
    ()
);

2.5 聚合函数:从基础到高级

Flink SQL 提供了丰富的内置聚合函数,以下分类介绍。

基础聚合
函数返回值描述
COUNT(*)BIGINT计数所有行
COUNT([DISTINCT] col)BIGINT统计非 NULL 值,可去重
SUM([DISTINCT] col)与输入同类型数值求和
AVG(col)DOUBLE平均值
MIN(col) / MAX(col)与输入同类型最小/最大值

所有聚合函数自动忽略 NULL。

高级聚合

COLLECT(col):将列的所有值收集为一个 MULTISET(多重集),可用于后续自定义处理。
LISTAGG(col [, delimiter]):将字符串拼接在一起,默认分隔符为 ,,例如 LISTAGG(name, '-')。

统计聚合

提供了一系列统计分析函数,如 STDDEV_POP、STDDEV_SAMP、VAR_POP、VAR_SAMP、CORR、COVAR_POP、COVAR_SAMP 以及 REGR_SLOPE 和 REGR_INTERCEPT 等线性回归函数。它们对于传感器数据异常检测、业务指标波动分析等场景非常有用。

近似聚合
  • APPROX_COUNT_DISTINCT(col) / APPROX_DISTINCT(col):基于 HyperLogLog 算法的基数估计,牺牲极少精度换取大幅降低的状态大小,适合去重计数的场景。
  • HISTOGRAM(col):返回一个 MAP,包含值的分布直方图,有助于快速了解数据分布。

2.6 开窗函数(Over 聚合)

Over 聚合不同于 Group By 窗口,它保留每一行数据,并在行的上下文中计算聚合值。语法:

SELECT 
  agg_func(col) OVER (
    [PARTITION BY col1[, col2, ...]]
    ORDER BY time_col
    range_definition
  )
FROM ...
  • ORDER BY 必须指定一个时间属性列(事件时间或处理时间)。
  • PARTITION BY 可选,指定分组的粒度,类似 Group By 的 key。
  • range_definition 定义聚合的数据范围,有两种方式:
    • 按行数:ROWS BETWEEN 5 PRECEDING AND CURRENT ROW(当前行及之前 5 行)。
    • 按时间区间:RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND CURRENT ROW(当前行时间之前 1 小时内的所有行)。

Over 聚合在实时特征工程、滑动累计指标、数据分析场景中十分常见,但要注意状态大小会随窗口范围和基数增大。

2.7 集合操作:UNION、INTERSECT、EXCEPT

Flink SQL 支持标准的集合操作,每个操作都有去重版本和保留所有版本:

  • UNION / UNION ALL
  • INTERSECT / INTERSECT ALL
  • EXCEPT / EXCEPT ALL
  • IN 子查询(仅支持单列)

注意:所有集合操作在流任务中都会产生撤回流。例如左流一条数据先到,但在右流尚未找到匹配时,它会先输出;随后右流对应数据到达后,需要将之前的假阳性结果撤回。这同样需要 Sink 支持 Retract。

此外,IN 子查询内部也维护状态,数量巨大时须设置 TTL。

2.8 ORDER BY 与 LIMIT 在流中的限制

实时任务中,ORDER BY 必须引用升序时间属性,即 Watermark 策略为严格升序 (ts AS ts) 或递增 (ts - INTERVAL '0.001' SECOND)。这是因为只有时间单调递增,Flink 才能确定排序结果的完整性,否则面对无限流无法给出全局有序的输出。

LIMIT 通常配合 ORDER BY 使用,比如“过去 1 小时内销售额最高的 10 个商品”。但如果不加窗口约束直接对无限流排序,Flink 将抛出异常。


三、列转行:从一行到多行

当一行数据里包含数组或需要拆分成多行时,列转行技术就派上用场了。

3.1 Array Expansion(数组列转行)

适用于将 ARRAY<STRING> 等数组类型的字段拍平,生成多行。例如日志上报时经常将多个事件打成数组批量上报,分析时需要拆开:

CREATE TABLE show_log_table (
    log_id BIGINT,
    show_params ARRAY<STRING>
) WITH (...);
-- 数据:+I[7, [a, b, c]]

SELECT log_id, t.show_param
FROM show_log_table
CROSS JOIN UNNEST(show_params) AS t (show_param);
-- 结果:7 -> a; 7 -> b; 7 -> c

UNNEST 相当于为每个数组元素生成一行,与 CROSS JOIN 配合完成转换。

3.2 Table Function(自定义列转行)

Table Function 本质是 UDTF(用户定义的表函数),逻辑更灵活。你可以像写 Hive UDTF 一样,通过 Java/Scala 定义拆分的规则。

使用方式:

  • INNER JOIN:如果 UDTF 返回空结果,那么该行被直接丢弃。
  • LEFT JOIN:UDTF 返回空时,该行保留,但 UDTF 相关字段填充 NULL。

例如,定义一个根据 userId 动态生成多行的函数:

public static class UserProfileTableFunction extends TableFunction<Integer> {
    public void eval(long userId) {
        if (userId <= 5) {
            collect(1);
        } else {
            collect(1);
            collect(2);
            collect(3);
        }
    }
}

注册后在 SQL 中通过 LATERAL TABLE 调用:

SELECT user_id, name, t.age, row_time
FROM source_table,
LATERAL TABLE(user_profile_table_func(user_id)) t(age);

这种方式为复杂的一对多转换提供了无限可能。


四、其他常用语句

除了核心的 DDL 和 DML,Flink SQL 还有一批非常实用的辅助语句。

4.1 EXPLAIN:查看执行计划

EXPLAIN PLAN FOR <query_statement_or_insert_statement>

它可以显示 SQL 的逻辑计划和经过优化后的物理执行计划,是性能调优和排查问题的一大利器。

4.2 USE:切换上下文

  • USE CATALOG catalog_name:切换 Catalog。
  • USE db_name:切换当前 Database。
  • USE MODULES module_name[, ...]:加载临时 Module(如内置函数扩展)。

4.3 SHOW:列出元数据信息

  • SHOW CATALOGS / SHOW CURRENT CATALOG
  • SHOW DATABASES / SHOW CURRENT DATABASE
  • SHOW TABLES / SHOW VIEWS
  • SHOW FUNCTIONS / SHOW MODULES

这些命令在 SQL 客户端交互式查询时非常方便。

4.4 LOAD / UNLOAD 模块

Module 是 Flink 中用于 UDF 扩展或系统功能增强的机制,通过 LOAD MODULE module_name 可以加载内置或自定义的模块,UNLOAD 则相反。示例:LOAD MODULE hive; 加载 Hive 兼容模块。

4.5 SET / RESET:调整配置

只能在 SQL CLI 中使用。SET 'key' = 'value' 用于修改环境配置,例如 SET 'table.planner' = 'blink';。RESET 可以重置指定 key 或所有配置为默认值。这对于临时调整作业行为而不修改 YAML 文件十分便利。

4.6 INSERT:写出数据

这是最常见的输出语句:

INSERT INTO target_table [(column1, column2, ...)]
SELECT ... FROM ...;

注意,流式作业中 INSERT INTO 通常是长期运行的,不同于批处理的一次性执行。

4.7 SQL Hints:临时的“魔法棒”

SQL Hints 允许在 DML 语句中通过注释的方式动态覆盖表的配置,非常适合临时调试或特殊场景。

SELECT *
FROM kafka_table1 /*+ OPTIONS('scan.startup.mode'='latest-offset') */;

上面的语句会忽略表定义中的 scan.startup.mode 配置,直接使用 latest-offset 进行查询。生产环境中不建议大量使用 Hints,因为会降低可维护性,但它作为临时工具有很强的灵活性。


五、总结

这篇文章系统梳理了 Flink SQL 的语法全景,从 DDL 建表的各种列类型、Watermark 与主键约束,到 DML 中 CTE、窗口 TVF、Group By 与撤回流、聚合函数、Over 聚合、集合操作、列转行,再到 EXPLAIN、SET 等辅助命令。掌握这些语法只是第一步,真正融会贯通还需要深入理解流式状态、时间语义和时区处理。

几个核心要点再强调一下:

  • 时间属性是流计算的灵魂,如果涉及事件时间千万别忘了定义 Watermark。
  • 窗口 TVF 是官方推荐的最佳实践,告别老式 GROUP BY TUMBLE 吧。
  • 普通 Group By 会产生撤回流,要根据下游存储的特性谨慎使用。
  • 善用 CTE 提高 SQL 可读性,用列转行处理非结构化数组,用状态 TTL 防止无限膨胀。
flink用法详解 无界流 (Unbounded Streams): 数据流理论上没有终点,持续不断地流入系统。Flink 会连续地处理这些事件,即使在处理过程中新的数据还在不断到来。 有界流 (Bounded Streams): 数据流有一个明确的起点和终点,处理完所有数据后任务即结束。Flink 可以像处理流一样处理批数据,采用相同的 API 并提供高效执行。编写一个Flink步骤 Source:flink的数据来源 集合 文件 socket kafka 总结:自定义Source Flink提供了数据源接口 阅读详情

相关推荐

Flink(十三)【Flink SQL(上)SqlClient、DDL、查询】

Flink SQL sql-client、DDL语句、查询语句

功不唐捐,玉汝于成 2502

【Flink SQL】Flink SQL 语法篇(十):EXPLAIN、USE、LOAD、SET、SQL Hints

如果熟悉 MySQL 的同学会非常熟悉这个子句,在 MySQL 中,USE 子句通常被用于切换库,那么在 Flink SQL 体系中,它的作用也是和 MySQL 中 USE 子句的功能基本一致,用于切换 Catalog,DataBase,使用 Module。

Data · Model · Agent · Repeat 3369

FLINK SQL语法(1)

Flink SQL Connector是一种用于在Flink SQL与外部数据源或数据汇之间建立连接的插件。它允许Flink SQL从外部数据源读取数据,并将处理后的数据写入到外部数据汇中。通过Connector,Flink SQL能够轻松实现对各种类型数据的实时处理和分析。在某些特殊情况下,用户可能需要自定义Connector来满足特定的需求。Flink提供了丰富的API和工具来支持用户自定义Connector。自定义Connector通常涉及以下几个步骤:1.定义Connector的工厂类。

王小工小工历程 2579

Flink SQL DDL

时间属性 (time attributes) :每个表模式结构 (schema) 的一部分。表属性 : 指定外部存储系统的元数据信息。主键约束 : 唯一性,且不为 NULL。

记录点点滴滴 965

大数据Flink(八十二):SQL语法的DDL:Create 子句

例如,我们可以使用元数据列从 Kafka 数据中读取 Kafka 数据自带的时间戳(这个时间戳不是数据中的某个时间戳字段,而是数据写入 Kafka 时,Kafka 引擎给这条数据打上的时间戳标记),然后我们可以在 Flink SQL 中使用这个时间戳,比如进行基于时间的窗口操作。如果只是简单的四则运算的话直接写在 DML 中就可以,但是计算列一般是用于定义时间属性的(因为在 SQL 任务中时间属性只能在 DDL 中定义,不能在 DML 语句中定义)。这些列本身是没有以物理形式存储到数据源中的。

Lansonli(蓝深李)的博客 1380

大数据Flink(九十六):DML:Deduplication

Deduplication 其实就是去重,也即上文介绍到的 TopN 中 row_number = 1 的场景,但是这里有一点不一样在于其排序字段一定是时间属性列,不能是其他非时间属性的普通列。在 row_number = 1 时,如果排序字段是普通列 planner 会翻译成 TopN 算子,如果是时间属性列 planner 会翻译成 Deduplication,这两者最终的执行算子是不一样的,Deduplication 相比 TopN 算子专门做了对应的优化,性能会有很大提升。可以看到其有回撤数据。

Lansonli(蓝深李)的博客 827

flink-sql所有语法详解

SET语句用于修改配置或列出配置。RESET语句用于将配置重置为默认值。CREATE语句用于将表/视图/函数注册到当前或指定的 Catalog 中。已注册的表/视图/函数可以在SQL查询中使用。NSERT语句用于向表中添加行数据。USE语句用于设置当前数据库或catalog,或更改模块的解析顺序和启用状态。select语句主要是从表中查询数据,然后将数据插入到其他表中。直接在页面中查看select的结果,目前平台还不支持。单个反斜杠就可以作为转义字符使用,在select查询中可以直接使用。

begefefsef的博客 1万+

大数据Flink(九十):Lookup Join(维表 Join)

Lookup Join 其实就是维表 Join,比如拿离线数仓来说,常常会有用户画像,设备画像等数据,而对应到实时数仓场景中,这种实时获取外部缓存的 Join 就叫做维表 Join。

Lansonli(蓝深李)的博客 3422

flink1.14 sql基础语法(一) flink sql表查询详解

flink sql表查询详解

qq_44665283的博客 8521

知识导航神器:Obsidian Breadcrumbs 插件全攻略

Parent: 插件Child: Breadcrumbs 用法这样,它就能识别出你和其他笔记的关系。

m0_73735578的博客 1628

Plant simulation、Flexsim、Automod、Emulate3D、VisuaComponent仿真软件对比

E3D在行业内以展示效果好,入门阶段易学易用人机界面友好,电控仿真连接方便不需要借助其他第三方软件,E3D平台开放度较高用户DIY程度强,数据分析功能针对要评定对象的KPI的可根据项目或者使用者需求进行评定。3.支持导入导出多种格式的文件,比如dwg、dxf、fbx、obj、3ds、step、stp、iges、skp、stl、wrl、 bmp 等等。3.软件自带模型组件库程序代码开放,用户可以引用、修改、拷贝,按照自己的逻辑修改模型,或者创建模型并保存到组件库与别人共享。3. 支持导出布局图片。

qq_43342303的博客 3576

Flink SQL DDL 和 窗口函数实战(含代码练习)

一、Flink SQL DDL 2019 年 8 月 22 日,Flink 发布了 1.9 版本,社区版本的 Flink 新增 了一个 SQL DDL 的新特性,但是暂时还不支持流式的一些概念的定义,比如说水位。 二、定义 create table 语句 从 kafka 中读取数据 可以体验一下,如果使用 ddl 的方式直接定义一个表从 kafka 中读取数据,并定义成一个表 CREATE TAB...

Brave_heart4pzj的博客 6157

基于表面肌电信号sEMG的手势识别——以Ninapro DB1数据集使用CNN网络识别为例

本文实验采用公共数据集Ninapro。该数据集数据量大,采集的动作丰富,每个单位数据集里面包括表面肌电信号、加速度计、手部运动学和动态数据等,记录了67名完整受试者和11名进行了至少50 次手部运动的截肢者的数据。NinaproDB1数据集包括27名完整的受试者(7 名女性和20名男性,其中2个左手和25 个右手) 的肌电信号。信号采集频率为100Hz。

树下一朵云的博客 2295

flink1.14 sql基础语法(二) flink sql表定义详解

flink1.14 sql基础语法(二) flink sql表定义详解

qq_44665283的博客 4155

射频测试基础知识总结

表示可以辐射到空间的电磁频率,频率范围从300KHz~110GHz之间,射频简称RF,是高频交流变化电磁波的简称,其每秒变化小于1000次被称为低频电流,超过10000次的称为高频电流,而射频就是这种高频电流。为了确保天线接收的信号能够在接收机的最后一级被正确的恢复,一个好的低噪音放大器需要在放大信号的同时产生尽可能低的噪音以及失真。两种,带内试验的范围也有一定的差别,比如,带内试验主要是检测信号的质量,如功率、频谱宽度、调制质量,而带外测试的是信号的杂散、谐波,主要是看对频带之外的干扰有多大。

cny70的博客 9627

CA(载波聚合)

文章目录CA基本概念1. CA分类2. Pcell、Scell以及Serving CellPcell(Primary Cell)Scell(Secondary Cell)3. Pcell、Scell部署场景场景1场景2场景3场景44. CA的协议控制4.1 Camping/Connetion Establishment:4.2 CC Management/SCell Addition/Release:4.3 Handover/Measurements:4.4 SCell激活 CA基本概念 CA也就是我们中文

你又来看我了,一起学习吧 4万+

flink1.13 sql基础语法(一)DDL、DML

flink1.13 sql基础语法(一)DDL、DML

qq_44665283的博客 2767

envi反演水质参数_遥感水质反演之反演模型

水质反演的框架图此为反演模型的章节第一部分,统计学基础:概率论、矩阵和数理统计的知识统计学知识框架# 1 基本统计概念知识在于应用,而非记忆!我们都是在样本的层面去操作数据的,以达到对总体性质的估计和推断,拿到一组数据首先进行基本的统计描述,常用的有:样本均值: 样本方差(调整方差)不是除以n,而是n-1, 标准差为样本方差开方即可皮尔逊积矩相关系数(简称相关系数): 相关系数范围在[-1,...

weixin_35275922的博客 3226

flink1.13 sql基础语法(二)join操作

flink1.13 sql基础语法(二)join操作

qq_44665283的博客 2963

基于C#通过PLCSIM ADV仿真软件实现与西门子1500PLC的S7通信方法演示

基于C#通过PLCSIM ADV仿真软件实现与西门子1500PLC的S7通信方法演示

Robot_PLC_HMI_Automation 3155

车辆网络安全ISO/SAE 21434解读(一)概述

ISO/SAE 21434 《道路车辆 网络安全工程》是SAE和ISO共同制定的一项针对道路车辆的网络安全标准,它是一个面向汽车行业全供应链(OEM及各级供应商)的车辆网络安全管理指导文件

xiaoxiabang的博客 8420

万字详述 Flink SQL 4 种时间窗口语义!(收藏)

DML:窗口聚合大家好我是老羊,由于窗口涉及到的知识内容比较多,所以博主先为大家说明介绍下面内容时的思路,大家跟着思路走。思路如下:⭐ 先介绍 Flink SQL 支持的 4 种时间窗口⭐ 分别详细介绍上述的 4 种时间窗口的功能及 SQL 语法⭐ 结合实际案例介绍 4 种时间窗口首先来看看 Flink SQL 中支持的 4 种窗口的运算。⭐ 滚动窗口(TUMBLE)⭐ ...

数据一哥,公众号:数据社 1万+

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Flink之SQL客户端与DDL操作

Flink SQL是Flink框架中的一种查询语言,用于对数据流和批处理作业执行SQL查询和转换操作。它提供了一种声明性的方式来处理数据,使得开发人员能够使用熟悉的SQL语法来操作流式和批处理数据。

积跬步,至千里。 1747

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Flink SQL 中动态修改 DDL 的属性

Flink 支持使用 HiveCatalog 来管理 Flink 的元数据信息, HiveCatalog 通过授权用户仅创建一次表和其他元数据对象,这样就避免了重复创建 kafka 流表...

JasonLee实时计算 7339

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Flink高级编程语法

Flink广播变量,计数器,缓存变量,分区,排序的语法介绍

a805814077的博客 1215

Flink SQL查询语法部分详解(提供需求、数据练习复现)

Hints、WITH、DISTINCT、窗口函数(TVFs)、OVER聚合、ORDER BY、模式检测(CEP)

weixin_52134189的博客 1874
上一篇: Flink 系列第19篇:深入理解 Flink SQL 的时间语义与时区处理:从原理到实战
下一篇: Flink 系列第21篇:Flink SQL 函数与 UDF 全解读:类型推导、开发要点与 Module 扩展
juniperhan
博客等级 码龄1年 132粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值