Flink 系列之二十九- Flink SQL - 中间算子:窗口聚合

之前做过数据平台,对于实时数据采集,使用了Flink。现在想想,在数据开发平台中,Flink的身影几乎无处不在,由于之前是边用边学,总体有点混乱,借此空隙,整理一下Flink的内容,算是一个知识积累,同时也分享给大家。

注意由于框架不同版本改造会有些使用的不同,因此本次系列中使用基本框架是 Flink-1.19.x,Flink支持多种语言,这里的所有代码都是使用java,JDK版本使用的是19
代码参考:https://github.com/forever1986/flink-study.git

目录

  • [1 Window Top-N](#1 Window Top-N)
    • [1.1 说明](#1.1 说明)
    • [1.2 示例演示](#1.2 示例演示)
  • [2 Window Deduplication](#2 Window Deduplication)
    • [2.1 说明](#2.1 说明)
    • [2.2 示例演示](#2.2 示例演示)

上一章针对了FlinkSQL中的水位线和窗口进行了讲解,那么这一章结合前面讲到的基于OVER函数的聚合TopN和Deduplication,实现在有窗口定义下的使用,下面统一做演示。

1 Window Top-N

1.1 说明

在《系列之二十七 - Flink SQL - 中间算子:OVER聚合》中讲过使用OVER函数来实现Top-N。这里加入上一章讲解的窗口,按照需求查询每个窗口的Top-N,以下是Top-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) -- relation applied windowing TVF
WHERE rownum <= N [AND conditions]

注意事项

  • 1)其中table_name替换为VTF窗口的写法,即可做到开窗求Top-N
  • 2)Window Top-N 需要 PARTITION BY 子句包含 窗口表值函数 或 窗口聚合 产生的 window_start 和 window_end
  • 3)不支持会话窗口

1.2 示例演示

示例说明:通过随机生成服务器cpu值,进行滚动窗口5秒内排名top-2的cpu值。为了演示说明方便,这里只生成一台服务器的数据

1)创建log表:使用它datagen的connector随机生成cpu值

sql 复制代码
CREATE TABLE log(
	id INT,
	cpu DOUBLE,
	ts AS cast(CURRENT_TIMESTAMP as timestamp(3)),
	WATERMARK FOR ts AS ts
) WITH (
  'connector' = 'datagen',
  'rows-per-second'='1',
  'fields.id.kind'='random',
  'fields.id.min'='1',
  'fields.id.max'='1',
  'fields.cpu.kind'='random',
  'fields.cpu.min'='1',
  'fields.cpu.max'='100'
);

2)结合Top-N和窗口查询:5秒长度滚动窗口,窗口内排名前2的cpu值

sql 复制代码
SET sql-client.execution.result-mode=TABLEAU; 
SELECT
  id,
  cpu,
  ts,
  rownum,
  window_start, 
  window_end
FROM
(
  SELECT 
    id , 
    cpu, 
    ts, 
    ROW_NUMBER() OVER(PARTITION BY window_start, window_end ORDER BY cpu desc) as rownum,
    window_start, 
    window_end
  FROM TABLE(TUMBLE(TABLE log, DESCRIPTOR(ts), INTERVAL '5' SECOND))
)
WHERE rownum<=2;

说明:从上图可以看到每个窗口不断地打印出前2的cpu值,[15,20)的窗口只打印一条是刚好这个窗口只有1条数据(19秒的时候生产的)

2 Window Deduplication

2.1 说明

在《系列之二十七 - Flink SQL - 中间算子:OVER聚合》中讲过使用OVER函数来实现Deduplication。这里加入上一章讲解的窗口,按照需求查询每个窗口的去重Deduplication,以下是Deduplication的语法:

sql 复制代码
SELECT [column_list]
FROM (
   SELECT [column_list],
     ROW_NUMBER() OVER (PARTITION BY window_start, window_end [, col_key1...]
       ORDER BY time_attr [asc|desc]) AS rownum
   FROM table_name) -- relation applied windowing TVF
WHERE (rownum = 1 | rownum <=1 | rownum < 2) [AND conditions]

注意事项

  • 1)其中table_name替换为VTF窗口的写法,即可做到开窗去重
  • 2)Window Top-N 需要 PARTITION BY 子句包含 窗口表值函数 或 窗口聚合 产生的 window_start 和 window_end
  • 3)不支持会话窗口。不支持处理时间,只支持事件时间

2.2 示例演示

示例说明:通过随机生成服务器cpu值,进行滚动窗口5秒内每台服务器最大cpu值。

1)创建log表:使用它datagen的connector随机生成cpu值

sql 复制代码
CREATE TABLE log(
	id INT,
	cpu DOUBLE,
	ts AS cast(CURRENT_TIMESTAMP as timestamp(3)),
	WATERMARK FOR ts AS ts
) WITH (
  'connector' = 'datagen',
  'rows-per-second'='1',
  'fields.id.kind'='random',
  'fields.id.min'='1',
  'fields.id.max'='2',
  'fields.cpu.kind'='random',
  'fields.cpu.min'='1',
  'fields.cpu.max'='100'
);

2)结合Top-N和窗口查询:5秒长度滚动窗口,窗口内不同服务器最大的cpu值

sql 复制代码
SET sql-client.execution.result-mode=TABLEAU;
SELECT
  id,
  cpu,
  ts,
  rownum,
  window_start, 
  window_end
FROM
(
  SELECT 
    id , 
    cpu, 
    ts, 
    ROW_NUMBER() OVER(PARTITION BY window_start, window_end, id ORDER BY cpu desc) as rownum,
    window_start, 
    window_end
  FROM TABLE(TUMBLE(TABLE log, DESCRIPTOR(ts), INTERVAL '5' SECOND))
)
WHERE rownum = 1;

说明:从上图可以看到每个窗口不断地打印出最大的cpu值
结语 :本章主要是将《系列之二十七 - Flink SQL - 中间算子:OVER聚合》中的Top-N和Deduplication场景在有窗口定义下的情况进行演示。下章还是继续回到FlinkSQL的中间算子。