FlinkSQL 中的窗口类型
在 Flink SQL 中,窗口(Windows)是处理无界数据流(Streaming)的核心机制。它将无界的数据流切分成有限大小的“桶”(buckets),并在这些桶上进行聚合计算(如 SUM、AVG 等)。
从 Flink 1.13 开始,官方推荐使用 窗口表值函数(Windowing TVFs, Window Table-Valued Functions) 来定义窗口,它比老版本的 Group Window 功能更强大、性能更好,且更符合 SQL 标准。
以下是 Flink SQL 中最主要的几种窗口类型及其详细介绍:
1. 滚动窗口 (Tumble Windows)
特点:
- 大小固定,窗口之间不重叠,也没有间隙。
- 每个元素只属于一个窗口。
适用场景:
- 计算每分钟的 PV/UV。
- 计算每小时的销售总额。
Flink SQL 语法 (TVF):
sql
SELECT window_start, window_end, SUM(price)
FROM TABLE(
TUMBLE(TABLE Bid, DESCRIPTOR(bidtime), INTERVAL '10' MINUTES)
)
GROUP BY window_start, window_end;
bidtime:时间属性列(Event Time 或 Processing Time)。INTERVAL '10' MINUTES:窗口大小(10分钟)。
2. 滑动窗口 (Hop Windows / Sliding Windows)
特点:
- 大小固定,但窗口之间有重叠。
- 由两个参数定义:窗口大小 (Size) 和 滑动步长 (Slide)。
- 一个元素可能会被分配到多个窗口中。
适用场景:
- 每隔 5 分钟,计算过去 1 小时内的活跃用户数(Size = 1小时, Slide = 5分钟)。
- 监控最近 10 分钟内的异常报错频率。
Flink SQL 语法 (TVF):
sql
SELECT window_start, window_end, SUM(price)
FROM TABLE(
HOP(TABLE Bid, DESCRIPTOR(bidtime), INTERVAL '5' MINUTES, INTERVAL '1' HOURS)
)
GROUP BY window_start, window_end;
INTERVAL '5' MINUTES:滑动步长(Slide)。INTERVAL '1' HOURS:窗口大小(Size)。
3. 累积窗口 (Cumulate Windows)
特点:
- 在指定的最大窗口长度内,按照步长定期触发计算,并累积之前的数据。
- 简单来说,它是“固定起点,动态终点”的窗口。
适用场景:
- 天级累计指标:从每天 00:00 开始,每隔 10 分钟计算一次当天截止到当前时间的累计 GMV(最大长度 24 小时,步长 10 分钟)。
Flink SQL 语法 (TVF):
sql
SELECT window_start, window_end, SUM(price)
FROM TABLE(
CUMULATE(TABLE Bid, DESCRIPTOR(bidtime), INTERVAL '10' MINUTES, INTERVAL '1' DAYS)
)
GROUP BY window_start, window_end;
INTERVAL '10' MINUTES:累积的步长(每10分钟触发并更新一次结果)。INTERVAL '1' DAYS:最大窗口大小(一天结束时窗口重置)。
4. 会话窗口 (Session Windows)
特点:
- 通过间隙时间 (Gap) 来切分窗口。如果一段时间内没有数据流入(超过了 Gap 长度),则当前的窗口关闭,新来的数据将开启一个新窗口。
- 窗口的长度是动态的,且每个 Key 的窗口边界可能不同。
适用场景:
- 用户行为分析:计算用户一次“活跃会话(Session)”内的点击次数(如果用户超过 30 分钟未操作,则认为会话结束)。
Flink SQL 语法 (TVF):
(注意:Session Window TVF 在 Flink 1.14+ 中引入)
sql
SELECT window_start, window_end, count(1)
FROM TABLE(
SESSION(TABLE Bid, DESCRIPTOR(bidtime), INTERVAL '30' MINUTES)
)
GROUP BY window_start, window_end, user_id;
INTERVAL '30' MINUTES:会话不活跃的超时时间(Gap)。
5. 渐变窗口 / 聚合窗口 (Over Windows)
特点:
- 与传统的 Group Window(将数据划分到不同的桶)不同,Over 窗口是针对每一条数据,计算其对应的一个窗口范围(类似于传统数据库的窗口函数
OVER (PARTITION BY ... ORDER BY ...))。 - 每一条数据都会触发一次计算。
适用场景:
- 计算当前行与前 10 行数据的平均值。
- 计算当前用户最近 1 小时内的累计消费金额(每来一笔算一次)。
Flink SQL 语法:
sql
SELECT order_id, order_time, amount,
SUM(amount) OVER (
PARTITION BY user_id
ORDER BY order_time
RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND CURRENT ROW
) as one_hour_sum
FROM Orders;
- 支持基于时间范围(
RANGE BETWEEN...)和基于行数(ROWS BETWEEN...)的定义。
总结与对比
| 窗口类型 | 窗口大小 | 窗口是否重叠 | 触发频率 | 典型应用场景 |
|---|---|---|---|---|
| Tumble (滚动) | 固定 | 否 | 窗口结束时一次性触发 | 统计每小时/每天的独立指标 |
| Hop (滑动) | 固定 | 是 | 每隔 Slide 时间触发一次 | 统计最近 N 分钟/小时的滑动指标 |
| Cumulate (累积) | 动态增长 | 是(包含关系) | 每隔 Step 时间触发,累积数据 | 天级累计 GMV、累计 UV |
| Session (会话) | 动态 | 否 | 超过 Gap 时间无数据时触发 | 用户单次访问会话分析 |
| Over (渐变) | 动态 | 是 | 每条数据流入都触发 | 实时滚动均值、最新 N 条数据聚合 |
最佳实践建议:
在 Flink 1.13 及以上版本中,编写 Flink SQL 时应优先使用 Window TVF 语法(即 SELECT * FROM TABLE(TUMBLE(...))),因为 TVF 支持性能优化(如 Local-Global 聚合)、Window Join 以及 Window Top-N 等高级功能。