Flink SQL Window Top-N窗口榜单的正确打开方式

1. Window Top-N 是什么

Window Top-N 是一种特殊的 Top-N:在每个窗口(window)内 ,对 N 个最大/最小值进行筛选,并且支持再叠加其它分区键(partition keys)。

Streaming 查询中,Window Top-N 不会像连续 Top-N 那样持续输出中间更新 ,而是只在窗口结束时输出最终 Top-N,并且窗口结束后会清理中间状态,因此如果你不需要"每条记录更新榜单",它通常性能更好。

2. Window Top-N 的关键前置条件

2.1 必须基于 Windowing TVF 或 Window Aggregation

Window Top-N 一般直接跟在 Windowing TVF(例如 TUMBLE/HOP/CUMULATE)后,或跟在 Window Aggregation(窗口聚合)后使用。

2.2 PARTITION BY 必须包含 window_start 和 window_end

Window Top-N 的 SQL 形式和普通 Top-N 相同,但额外要求:PARTITION BY 必须包含 window_startwindow_end(来自 Windowing TVF 或 Window Aggregation 的结果),否则优化器无法翻译成 Window Top-N。

2.3 Windowing TVF 会产出哪些窗口字段

Windowing TVF 会返回一个包含原始字段的关系表,并额外生成 window_startwindow_endwindow_time 三个字段。

3. Window Top-N 的标准语法模板

下面这个模板建议严格照抄结构(只改字段名与 N),以保证优化器能识别:

sql 复制代码
SELECT [column_list]
FROM (
  SELECT [column_list],
         ROW_NUMBER() OVER (
           PARTITION BY window_start, window_end [, col_key1...]
           ORDER BY col1 [asc|desc][, col2 [asc|desc]...]
         ) AS rownum
  FROM table_name   -- 必须是应用了 Windowing TVF 或 Window Aggregation 的关系
)
WHERE rownum <= N [AND conditions];

4. 示例一:Window Top-N 跟在 Window Aggregation 后(Top 3 供应商销售额)

4.1 业务目标

每个 10 分钟滚动窗口,计算销售额最高的 Top3 供应商(supplier)。

4.2 SQL 写法

sql 复制代码
SELECT *
FROM (
  SELECT *,
         ROW_NUMBER() OVER (
           PARTITION BY window_start, window_end
           ORDER BY price DESC
         ) AS rownum
  FROM (
    SELECT
      window_start, window_end,
      supplier_id,
      SUM(price)  AS price,
      COUNT(*)    AS cnt
    FROM TABLE(
      TUMBLE(TABLE Bid, DESCRIPTOR(bidtime), INTERVAL '10' MINUTES)
    )
    GROUP BY window_start, window_end, supplier_id
  )
)
WHERE rownum <= 3;

5. 示例二:Window Top-N 直接跟在 Windowing TVF 后(Top 3 单条最高价记录)

5.1 业务目标

每个 10 分钟窗口,找出价格最高的 Top3 记录(不先聚合)。

5.2 SQL 写法

sql 复制代码
SELECT *
FROM (
  SELECT
    bidtime, price, item, supplier_id,
    window_start, window_end,
    ROW_NUMBER() OVER (
      PARTITION BY window_start, window_end
      ORDER BY price DESC
    ) AS rownum
  FROM TABLE(
    TUMBLE(TABLE Bid, DESCRIPTOR(bidtime), INTERVAL '10' MINUTES)
  )
)
WHERE rownum <= 3;

6. 限制与注意事项

6.1 Batch 模式下不支持 SESSION Window Top-N

目前 SESSION Window Top-N 在 batch 模式还不支持。

6.2 Windowing TVF 路径的支持范围

当前只支持 Window Top-N 跟在 Windowing TVF 的 TUMBLE / HOP / CUMULATE 后;Windowing TVF 的 Session Window 路径将来会支持。

7. 工程化落库建议(主键怎么设计)

7.1 保存"窗口榜单结果"时的主键组合

如果你要把 Window Top-N 落到外部存储,通常建议把窗口边界作为主键的一部分,比如:

  • window_start + window_end + 分区键(supplier_id / category)
  • 如果需要保存榜单位置,再加 rownum

7.2 不输出 rownum 的策略

如果你不希望把 rownum 输出到下游(减轻下游写压力),可以外层 SELECT 不带 rownum,让消费端自行排序展示;但此时主键应回归业务实体(如 supplier_id / item_id)+ 窗口字段。

8. 性能调优:table.exec.rank.topn-cache-size

Window Top-N 底层依然依赖 Rank/TopN 的实现细节,缓存参数 table.exec.rank.topn-cache-size(默认 10000)在分区键基数很大时很关键。

当你发现延迟、反压明显,且分区数量巨大时,可尝试调大(如 200000)并观测 GC 与吞吐变化。

相关推荐
wsx_iot4 小时前
MySQL 的 MVCC(多版本并发控制)详解
数据库·mysql
Hello.Reader4 小时前
Flink SQL Deduplication用 ROW_NUMBER 做流式去重
大数据·sql·flink
Shingmc34 小时前
MySQL表的增删改查
数据库·mysql
敲上瘾4 小时前
MySQL主从集群解析:从原理到Docker实战部署
android·数据库·分布式·mysql·docker·数据库架构
电子_咸鱼4 小时前
【QT——信号和槽(1)】
linux·c语言·开发语言·数据库·c++·git·qt
pandarking4 小时前
[CTF]攻防世界:web-unfinish(sql二次注入)
前端·数据库·sql·web安全·ctf
程序猿20234 小时前
MySQL索引性能分析
数据库·mysql
TDengine (老段)4 小时前
TDengine 新性能基准测试工具 taosgen
大数据·数据库·物联网·测试工具·时序数据库·tdengine·涛思数据
波波仔864 小时前
行存储与列存储的区别
数据库·clickhouse·行存储·列储存