一、概念
在Flink中,TopN计算是指从数据流中选取前N个元素,通常根据某个指标进行排序。TopN计算可以在全局范围内进行,也可以在窗口内进行。窗口TopN计算是指在特定的时间窗口或计数窗口内进行TopN计算。这些操作在实时数据分析、监控和推荐系统中非常常见。
二、案例
2.1 topN
魔法部在英国各地追踪巫师施展的每一个法术,并想知道每个巫师最喜欢的两个法术。 Flink SQL可用于计算连续聚合值,因此如果我们知道巫师施展的每个法术,就可以计算出他们施展该法术的总次数,此结果可用在OVER窗口上以计算Top-N
。先对上一步计算的结果按wizard
列进行分区,然后再根据施法次数(times_cast DESC
)降序排序。最后只保留row_num <= 2的行,从而找到每个巫师最喜欢的2个法术。
代码:
CREATE TEMPORARY TABLE spells_cast (
wizard STRING,
spell STRING
) WITH (
'connector' = 'faker',
'fields.wizard.expression' = '#{harry_potter.characters}',
'fields.spell.expression' = '#{harry_potter.spells}'
);
-- 找出每个巫师最喜欢的两个法术
SELECT wizard, spell, times_cast
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY wizard ORDER BY times_cast DESC) AS row_num -- 按法术次数降序排序
FROM (SELECT wizard, spell, COUNT(*) AS times_cast FROM spells_cast GROUP BY wizard, spell) -- 计算每个巫师施展的各种法术的次数
)
WHERE row_num <= 2;
结果:
2.2 窗口topN
Flink有:滚动窗口、滑动窗口、会话窗口这几种,在此以滚动窗口为例进行示范,有一张订单表 orders,表中包含:下单时间、金额、商品、供货商,要求按照供货商分组每2分钟统计一次汇总的销售金额,并取出每个窗口下汇总销售价格排行前三的供货商名单以及对应销售金额。
代码如下:
CREATE TEMPORARY TABLE orders (
bidtime TIMESTAMP(3),
price DOUBLE,
item STRING,
supplier STRING,
WATERMARK FOR bidtime AS bidtime - INTERVAL '5' SECONDS -- 定义watermark
) WITH (
'connector' = 'faker', -- Faker 连接器仅在 VVR-4.0.12 及以上支持
'fields.bidtime.expression' = '#{date.past ''30'',''SECONDS''}',
'fields.price.expression' = '#{Number.randomDouble ''2'',''1'',''150''}',
'fields.item.expression' = '#{Commerce.productName}',
'fields.supplier.expression' = '#{regexify ''(Alice|Bob|Carol|Alex|Joe|James|Jane|Jack)''}',
'rows-per-second' = '100'
);
-- 取出销售排名前三的供应商
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
, SUM(price) as price
, COUNT(*) as cnt
FROM TABLE(TUMBLE(TABLE orders, DESCRIPTOR(bidtime), INTERVAL '2' MINUTES))
GROUP BY window_start, window_end, supplier
)
) WHERE rownum <= 3;
结果: