Flink sql 之 TopN 与 StreamPhysicalRankRule (源码解析)
基于flink1.14的源码做解析
公司内有很多业务方都在使用我们Flink sql平台做TopN的计算,今天同事突然问到我,Flink sql 是怎么实现topN的 ?
蒙圈了,这块源码没看过啊 ,业务要问起来怎么办,赶快打开源码补一下
拿到这个问题先冷静分析一下范围
首先肯定属于Flink sql模块,源码里面肯定是在flink-table-planner包里面,接着topN那不就是ROW_NUMBER嘛,是个函数呀
既然如此那就从flink源码的系统函数作为线索开始找起来,来到 org.apache.calcite.sql.fun.SqlStdOperatorTable类

果然找到了,那calcite的某个rule肯定有个地方判断了它,继续查调用链

不出所料,FlinkLogicalRankRuleBase这个calcite的rule里面果然根据这个function的类型来确定rank的类型了
看下这个rule的匹配条件

这里也好理解,overAgg的时候会判断这个rank以及对应的类型

这是只是做了一下简单的提取了rank的字段啊,提取谓语啊,提取表达式啊这一些拿信息的操作
然后直接生成新的relNode叫FlinkLogicalRank通过transformTo直接返回了这个等价节点
既然是relNode那肯定又会有calcite的rule去处理它,来找一找

批处理的就不管了,从名字就可以看出来我们要找的类了
看个不带window的吧

返回StreamPhysicalRank
这个类是一个FlinkPhysicalRel是可以转换成execNode的

返回的这个StreamExecRank就是可以转换成具体的Flink的算子了,具体逻辑就在里面了
接下来看下row_number的具体逻辑,找到方法translateToPlanInternal
根据策略主要分为三种类型
AppendFastStrategy (输入仅包含插入时)
RetractStrategy (输入包含update和delete)
UpdateFastStrategy (输入不应包含删除且输入有给定的primaryKeys且按字段排序时)
来看个retractStrategy的吧

先通过sort的字段获取一个用于排序RowData的比较器 ComparableRecordComparator
根据比较器创建 RetractableTopNFunction
这个类还有两个主要的状态数据结构

dataState这个map用来存放当key相同的所有数据会放在同一个list里面
treeMap这个可排序的map就是通过上面我们sql里面定义的sort by 来排序数据的,Long是指这个相同的key有多少个record
!!!!!!!!!!! 那就是用java的treeMap排序呗
继续往下看

主逻辑就是这个了
每进入一条数据,会根据这条数据的类型划分
当数据是Insert , UPDATE_AFTER类型是会走 emitRecordsWithRowNumber()方法
当数据是UPDATE_BEFORE,DELETE类型会走 retractRecordWithRowNumber ()方法
来看下具体逻辑先看INSERT的

遍历treeMap

解读一下,当数据是insert数据的时候
按顺序遍历treeMap
当遍历过程中发现遍历的key与当前数据的key相同时,和当前数据key相同的所有数据数据(dataState中的LIST),全部撤回并且更新他们的rowNumber+1
继续遍历treeMap
之后的数据全部撤回UpdateBefore,并且向下游发送UpdateAfter使rowNumber+1,遍历直到已经到第TopN个数据循环结束
当数据是DELETE类型的时候,会和Insert反过来,当前key之后的数据全部撤回,然后rowNumber-1
整个处理流程差不多就结束了,可以看到rowNumber当N较大且排序变化频繁的时候,性能消耗还是非常大的,极端情况下游的数据会翻很多倍
这个还需要注意在其他两个策略中还有一个参数,table.exec.topn.cache-size

影响下面这个本地lruCache的大小

调大可以减少状态的访问,可以按需要添加
Flink sql 之 TopN 与 StreamPhysicalRankRule (源码解析)的更多相关文章
- [源码解析] GroupReduce,GroupCombine 和 Flink SQL group by
[源码解析] GroupReduce,GroupCombine和Flink SQL group by 目录 [源码解析] GroupReduce,GroupCombine和Flink SQL grou ...
- Flink 源码解析 —— 源码编译运行
更新一篇知识星球里面的源码分析文章,去年写的,周末自己录了个视频,大家看下效果好吗?如果好的话,后面补录发在知识星球里面的其他源码解析文章. 前言 之前自己本地 clone 了 Flink 的源码,编 ...
- Flink 源码解析 —— 如何获取 ExecutionGraph ?
https://t.zsxq.com/UnA2jIi 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac 上搭建 Flink 1.6. ...
- Flink 源码解析 —— 深度解析 Flink 是如何管理好内存的?
前言 如今,许多用于分析大型数据集的开源系统都是用 Java 或者是基于 JVM 的编程语言实现的.最着名的例子是 Apache Hadoop,还有较新的框架,如 Apache Spark.Apach ...
- Flink 源码解析 —— 如何获取 JobGraph?
JobGraph https://t.zsxq.com/naaMf6y 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac 上搭建 F ...
- Flink 源码解析 —— Flink JobManager 有什么作用?
JobManager 的作用 https://t.zsxq.com/2VRrbuf 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac ...
- Flink 源码解析 —— JobManager 处理 SubmitJob 的过程
JobManager 处理 SubmitJob https://t.zsxq.com/3JQJMzZ 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1 ...
- Flink Metrics 源码解析
Flink Metrics 有如下模块: Flink Metrics 源码解析 -- Flink-metrics-core Flink Metrics 源码解析 -- Flink-metrics-da ...
- Flink 源码解析 —— 深度解析 Flink 序列化机制
Flink 序列化机制 https://t.zsxq.com/JaQfeMf 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac 上搭 ...
随机推荐
- 程序解决十苹果问题 Java
程序解决十苹果问题 Java 题目:10个苹果,其中有9个重量相同,剩余1个相比其它重量不同(或重或轻,不得而知),使用天平比较三次,找出重量特殊的那一个 import org.junit.Test; ...
- JS 处理图片平铺问题
background: url("../../../assets/image/center.png") no-repeat; // 让图片不平铺 overflow: hidde ...
- Win10 下安装Ubuntu 21.04桌面版 双系统 并设置win10为默认启动系统 详细教程
@ 目录 〇.写在前面 〇 - Plus:如何进入BIOS 〇 - Plus - Plus:U盘启动快捷键 一.磁盘分区:Win10划分未分配空间 二.下载Ubuntu 21.04镜像 三.安装U盘启 ...
- 在同一台计算机中运行多个MySQL服务
目录 一.问题的来源 二.配置 1. 修改原来MySQL系统的my.ini文件 2. 修改注册表 3. 重新启动服务 4. 最终效果 一.问题的来源 这个学期里我需要修读<数据库系统>的课 ...
- Python常见问题 - python3 requests库提示警告InsecureRequestWarning的问题
当使用 requests 库发送请求时报了以下警告 D:\python3.6\lib\site-packages\urllib3\connectionpool.py:847: InsecureRequ ...
- docker&flask快速构建服务接口(二)
系列其他内容 docker快速创建轻量级的可移植的容器✓ docker&flask快速构建服务接口✓ docker&uwsgi高性能WSGI服务器生产部署必备 docker&g ...
- xxl-job <=2.0.2 反序列化漏洞
xxl-job <=2.0.2 反序列化漏洞 搭建 https://github.com/xuxueli/xxl-job/releases/tag/2.0.2 下载源码,导入idea,mysql ...
- Redis——set,hash与列表
一.List列表 基于Linked List实现 元素是字符串类型 列表头尾增删快,中间增删慢,增删元素是常态 元素可以重复出现 最多包含2^32-1元素 列表的索引 从左至右,从0开始 从右至左,从 ...
- Docker部署启动错误,需要手动进入Docker的容器里,启动程序,排查错误
#docker-compose build --no-cache //重新创建容器,不管有没有 #docker-compose up #docker-compose up -d //后台启动并运行容器 ...
- docker学习笔记(一)--ubunru18.04下面安装docker18.03
我是在本地安装的虚拟机,再搭建的环境,虚拟机的安装可以参考下面的博客: https://blog.csdn.net/u013142781/article/details/50529030 安装好了之后 ...