flink二开,实现了batch lookup join(附源码)

大数据(9h)FlinkSQL之Lookup Join ttl FOR SYSTEM_TIME AS OF Processing Time Temporal Join lookup join lookup cache Flink查询缓存 lookup.cache.max-rows lookup.cache.ttl 阅读详情

本文转载自:大数据羊说的一篇公众号文章,这里只做学习用,没有任何盈利行为。

1.序篇

书接上回,上节说到了博主发现由于在 flink sql 中 lookup join 访问外部维表存在的性能问题。

由此诞生了一个想法,以 Redis 维表为例,Redis 支持 pipeline 批量访问模式,因此 flink sql lookup join 能不能按照 DataStream 方式一样,先攒一批数据 ,然后使用 Redis pipeline 批量访问外部存储。博主亲切的将这个功能称为 flink sql batch lookup join,本节就是讲述博主基于 flink 源码对此功能的实现。

废话不多说,咱们先直接上本文的目录和结论,小伙伴可以先看结论快速了解博主期望本文能给小伙伴们带来什么帮助:

直接来一个实战案例:博主以曝光用户日志流关联用户画像(年龄、性别)维表为例介绍 batch lookup join 具有的基本能力(怎么配置参数,怎么写 sql,最终效果咋样)。
batch lookup join:主要介绍 batch lookup join 的功能是从 flink transformation 出发,确定要 batch lookup join 涉及改动的地方以及其实现思路、原理。也会教给大家一些改动源码来实现自己想要的一些功能的思路。
总结及展望:目前的 batch lookup join 实现其实不符合 sql 的原始语义,后续大家可以按照 sql 标准自己做一些实现

2.来一个实战案例

2.1.预期的输入、输出数据

来看看在具体场景下,对应输入值的输出值应该长啥样。

需求指标:使用曝光用户日志流(show_log)关联用户画像维表(user_profile)关联到用户的画像(性别,年龄段)数据。

来一波输入数据:

曝光用户日志流(show_log)数据(数据存储在 kafka 中):

log_idtimestampuser_id
12021-11-01
22021-11-0100:03:00
32021-11-0100:05:00
42021-11-0100:06:00
52021-11-0100:07:00

用户画像维表(user_profile)数据(数据存储在 redis 中):

user_id(主键)agesex
a12-18男
b18-24女
c18-24男

注意:redis 中的数据结构存储是按照 key,value 去存储的。其中 key 为 user_id,value 为 age,sex 的 json。如下图所示:

user_profile redis
预期输出数据如下:

log_idtimestampuser_idagesex
12021-11-01 00:01:03a12-18男
22021-11-01 00:03:00b18-24女
32021-11-01 00:05:00c18-24男
42021-11-01 00:06:00b18-24女
52021-11-01 00:07:00c18-24男

2.2.batch lookup join sql 代码

batch lookup join sql 代码和原来的 lookup join sql 代码一模一样。如下 sql。

CREATE TABLE show_log (
    log_id BIGINT,
    `timestamp` as cast(CURRENT_TIMESTAMP as timestamp(3)),
    user_id STRING,
    proctime AS PROCTIME()
)
WITH (
  'connector' = 'datagen',
  'rows-per-second' = '10',
  'fields.user_id.length' = '1',
  'fields.log_id.min' = '1',
  'fields.log_id.max' = '10'
);

CREATE TABLE user_profile (
    user_id STRING,
    age STRING,
    sex STRING
    ) WITH (
  'connector' = 'redis',
  'hostname' = '127.0.0.1',
  'port' = '6379',
  'format' = 'json',
  'lookup.cache.max-rows' = '500',
  'lookup.cache.ttl' = '3600',
  'lookup.max-retries' = '1'
);

CREATE TABLE sink_table (
    log_id BIGINT,
    `timestamp` TIMESTAMP(3),
    user_id STRING,
    proctime TIMESTAMP(3),
    age STRING,
    sex STRING
) WITH (
  'connector' = 'print'
);

-- lookup join 的 query 逻辑
INSERT INTO sink_table
SELECT 
    s.log_id as log_id
    , s.`timestamp` as `timestamp`
    , s.user_id as user_id
    , s.proctime as proctime
    , u.sex as sex
    , u.age as age
FROM show_log AS s
LEFT JOIN user_profile FOR SYSTEM_TIME AS OF s.proctime AS u
ON s.user_id = u.user_id

可以看到 lookup join 和 batch lookup join 的代码是完全相同的,唯一的不同之处在于,batch lookup join 需要设置 table config 参数,如下图所示:

table config

2.3.batch lookup join 效果

将原生 lookup join 和 batch lookup join 的效果做个对比:

原生的 lookup join:每输入一条数据,访问外部维表获取到结果输出一条数据,如下图所示。lookup join
博主实现的 batch lookup join:是每攒够 30 条数据或者每 5s(防止数据量少的情况下,长时间不输出数据) 就利用 redis pipeline 能力访问外部存储一次。然后批量输出结果,如下图所示。大大提高了吞吐。
batch lookup join

3.batch lookup join 实现

3.1.怎么知道应该改哪部分源码?

博主将通过下面几个问题去交给大家怎么改源码去实现自己的功能。

  1. 改源码的有哪些比较好的思路?
  • 结论:首先就是参考类似模块的实现(不会写,但是我会抄啊!),比如本文要实现 batch lookup join,必然要参考原生的 lookup join 去实现。
  1. 大家在改 flink 源码时,因为 flink 源码的模块太多了,项目非常庞大,往往第一步碰到的问题不是怎么去实现这个功能,而是应该在什么地方去改才能实现!
  • 结论:一个 flink 的任务(DataStream\Table\SQL)所有的精华精华精华都集中在 transformation 中!!!只要是涉及到算子实现的东西,小伙伴萌就可以到 transformation 中去寻找。可以将断点打在每一个 operator 的构造器或者 open 方法中就可以看到其实在哪一步构造和初始化的。这样就能顺着调用栈往前回溯而确定要改哪部分代码了。

3.2.lookup join 原理

3.2.1.transformation

在实现 batch lookup join 之前,当然要从原生的 lookup join 的实现开始入手,看看 flink 官方大大是怎么实现的,具体 transformation 如下图所示:

transformation
具体的实现逻辑承载在 org.apache.flink.streaming.api.operators.ProcessOperator,org.apache.flink.table.runtime.operators.join.lookup.LookupJoinRunner 中。

3.2.2.LookupJoinRunner

LookupJoinRunner 中的数据处理逻辑集中在 processElement 中。

访问外部维表的逻辑
可以看到上图,LookupJoinRunner 又内嵌了一层 fetcher 来实现具体的 lookup 逻辑。

  1. 其中 fetcher:就是根据 flink sql lookup join 逻辑生成的 lookup join 的代码实例;
  2. 其中 collector:collector 的主要功能就是将原始数据 RowData 和 lookup 到的 RowData 的数据合并为 JoinedRowData 结果,然后输出。
    接下来详细看看 fetcher 和 collector。

3.2.3.fetcher

transformation fetcher
把这个 fetcher 的代码 copy 出来瞅瞅。

fetcher
fetcher 内嵌了 RedisRowDataLookupFunction 来作为最终访问外部维表的函数。

3.2.4.RedisRowDataLookupFunction

访问 redis 获取到数据。

RedisRowDataLookupFunction

3.2.5.collector

transformation collector
把这个 collector 的代码 copy 出来瞅瞅。

collector

3.3.lookup join 算子实现调用链

是不是感觉一个 lookup join 的调用链贼复杂。

因为 batch lookup join 是完全参考 lookup join 去实现的,所以接下来博主介绍一下整体的调用链关系,这就会方便后续设计 batch lookup join 实现方案的时候去确定具体修改哪一部分代码。

调用链
整体的调用逻辑如下:

  1. ProcessOpeartor 把 原始 RowData 传给 LookupJoinRunner
  2. LookupJoinRunner 把 原始 RowData 传给根据 sql 代码生成的 fetcher
  3. fetcher 中把 原始 RowData 传给 RedisRowDataLookupFunction 然后去 lookup 维表,lookup 到的结果数据为 lookup RowData
  4. collector 把 原始 RowData 和 lookup RowData 数据合并为 JoinedRowData 然后输出。

3.4.batch lookup join 设计思路

还是一样,先看看设计思路最终的结论,batch lookup join 算子调用链设计如下:

batch lookup 调用链
详细说明一下设计思路:

  1. 如果想做到批量访问外部存储(Redis)的数据。可以推断出 RedisRowDataLookupFunction 的输入需要是 List<原始 RowData> ,输出需要是 List。其中输入数据输入到 RedisRowDataLookupFunction 中后,使用 Redis pipeline 去批量访问外部存储,然后把结果 List 输出。
  2. 由 RedisRowDataLookupFunction 的输出数据为 List 推断出 collector 输入数据格式必然是 List<原始 RowData>。由于在 lookup join 中 collector 的逻辑就是将 原始 RowData 和 lookup RowData 合并为 JoinedRowData,将结果输出。因此 collector 这里就是将 List<原始 RowData> 和 List 进行遍历合并,一条一条的输出 JoinedRowData。
  3. 同样 RedisRowDataLookupFunction 的输入数据是 fetcher 传入的,则推断出 fetcher 输入数据格式必然是 List<原始 RowData>。
  4. 由于 fetcher 输入是 List<原始 RowData>,则 LookupJoinRunner 输出到 fetcher 的数据也需要是 List<原始 RowData>。但是 ProcessOpeartor 只能传给 LookupJoinRunner 原始 RowData,因此可以得出我们的每攒 30 条数据或者每隔 5s 的逻辑就能确定需要在 LookupJoinRunner 中做了。

思路有了,那么 batch lookup join 涉及到的改动项也就能确认了。

  1. 新建一个 BatchLookupJoinRunner:实现攒批逻辑(每攒 30 条数据或者每隔 5s),其中攒批的数据放在 ListState 中,以防止丢失,在 table config 中的 is.dim.batch.mode 设置为 true 时使用此 BatchLookupJoinRunner。
  2. 代码生成的 fetcher:将原来输入的 原始 RowData 改为 List<原始 RowData>。
  3. 新建一个 RedisRowDataBatchLookupFunction:实现将输入的批量数据 List<原始 RowData> 拿到之后使用 redis pipeline 批量访问外部存储,获取到 List 结果数据给 collector。
  4. 代码生成的 collector:将原来 lookup join 中的输入 原始 RowData,lookup RowData 改为 List<原始 RowData>,List,添加遍历循环 List<原始 RowData>,List,按顺序合并 List 中的每一项 原始 RowData,lookup RowData 输出 JoinedRowData 的逻辑。

3.5.batch lookup join 的最终效果

3.5.1.transformation

可以看到 is.dim.batch.mode 设置为 true 时,transformation 如下。transformation 中的重点处理逻辑就是 BatchLookupJoinRunner

batch transformation

3.5.2.BatchLookupJoinRunner

BatchLookupJoinRunner

3.5.3.fetcher

fetcher

3.5.4.RedisRowDataBatchLookupFunction

RedisRowDataBatchLookupFunction 拿到输入的 List 数据,调用 Redis pipeline 批量访问外部存储。

RedisRowDataBatchLookupFunction

3.5.5.collector

sql 生成的 collector 代码如下:

collector

3.6.待改进项

目前上述方案实现的不足之处如下:

  1. batch 的执行逻辑与 sql 原始的语义不一致。因为从 sql 上看是完全没有这种 batch lookup join 的语义的。
  2. 其中每 5s博主简单实现了下,完全基于数据驱动的每 5s 攒一批,不是基于 onTimer 驱动的。可能会出现来了一条数据之后,5 min 内都没有来数据,则数据就不输出了。
  3. 没有考虑实现代码的抽象,以实现功能为主,所以很多基于源码的改动都是直接 copy 出来了另一个方法实现。

4.xdm 怎么使用这个功能?

打包项目 重新把下面两个模块 install (mvn clean install) 到本地仓库中。
在这里插入图片描述
然后在你的项目中引用两个 blink 包即可使用。使用方法就是只需要把 table config 的 is.dim.batch.mode 设置为 true,代码还按照 lookup join 的方式写即可。

从Dinky聊聊Flink的二次开发 这几天研究了一下Dinky,确实是一款很不错的软件,功能很强大,也很实用,可以极大的方便我们flink sql的开发工作,同时他也支持其他一些主流数据库的SQL,像starrocks。Dinky号称基于Flink二次开发,没有侵入Flink,所以这一点就值得我们学习,为了了解Dinky我自己也搭建了一套Dinky环境,确实使用起来非常舒适 ,搭建过程也是比较容易,下面简单列一下搭建过程。 阅读详情

相关推荐

Flink的Look Up Join详解

- 定义主流订单表(从 Kafka/Socket 等)) WITH ('connector' = 'kafka', -- 示例,这里仅做说明-- 定义 MySQL 维表) WITH ('lookup.cache.max-rows' = '5000', -- 启用缓存,最多缓存 5000 条'lookup.cache.ttl' = '60s', -- 缓存条目的 TTL 为 60 秒'lookup.max-retries' = '3' -- 遇到网络或其他错误时最多重试 3 次。

weixin_50227709的博客 2883

Flink Lookup Join(维表 Join)

Lookup Join 其实就是维表 Join,比如拿离线数仓来说,常常会有用户画像,设备画像等数据,而对应到实时数仓场景中,这种实时获取外部缓存的 Join 就叫做维表 Join。

别这么骄傲 1675

flink sql 知其所以然(十五):改了改源码,实现了个 batch lookup join(附源码)

看了那么多的技术文,你能明白作者想让你在读完文章后学到什么吗?大数据羊说的文章会让你明白

qq_34608620的博客 2952

Flink SQL Join 全面指南:Regular / Interval / Temporal / Lookup 与表函数连接的实战与原理

Flink SQL 支持对动态表进行复杂而灵活的连接(Join)操作,是流式数据关联、维表补全、事件对齐等场景的核心能力。本文基于 Apache Flink 官方文档与仓库源码,系统讲解 Regular Join、Interval Join、Temporal Join、Lookup Join、数组展开(UNNEST)与表函数 Join 六类连接操作的语法、适用场景、状态语义与底层实现,帮助你在批流

gitblog_00238的博客 443

大数据Flink(九十):Lookup Join(维表 Join)

Lookup Join 其实就是维表 Join,比如拿离线数仓来说,常常会有用户画像,设备画像等数据,而对应到实时数仓场景中,这种实时获取外部缓存的 Join 就叫做维表 Join。

Lansonli(蓝深李)的博客 3426

Spark离线数仓与Flink实时数仓双轨架构部署实战解析

数据仓库是企业数据分析和报表的核心基础设施,通常分为离线与实时两条技术链路。离线数仓以Spark为计算引擎,按ODS、DWD、DWS、ADS分层加工,支撑T+1周期性报表;实时数仓则依赖Flink的流处理能力,通过CDC接入业务库变更,经维表关联与实时ETL落地Doris,服务秒级大屏与监控。两者在架构上互补,但双轨并行带来的数据一致性、版本兼容和参数调优问题,是工程实践中的普遍痛点。围绕一套双轨数仓项目源码,从环境部署、离线ETL链路、Spark与Flink核心参数,到离线Hive与实时Doris的对账机

weixin_29034963的博客 140

Folia 手机端安装 15 分钟完成:加到主屏幕,装完就有一台全屏歌词动画播放器

Folia 是支持网易云、QQ 音乐、酷狗、Navidrome 与本地曲库的歌词动画播放器。这篇文章带你在 15 分钟内完成 Folia 手机端安装:手机主屏幕上多出一个 Folia 图标,点开就是全屏歌词动画播放器,在线搜歌、播 NAS 曲库都能干。 [![Folia 手机端首页封面轮播与在线歌曲入口界面](https://raw.gitcode.com/GitHub_Trending/fo/

gitblog_00623的博客 115

基于Flink的商品实时推荐系统:从离线T+1到秒级更新实战

实时计算引擎通过事件时间、状态管理和精确一次语义,将无界数据流转化为低延迟的推荐结果。其核心原理在于滑动窗口聚合与状态后端选型,技术价值是消除离线批处理的时间差,让用户行为在秒级内影响推荐列表。典型应用场景包括电商商品推荐、内容分发和广告投放,其中商品实时推荐系统需要融合短期兴趣与长期画像,并借助Kafka、Flink SQL和JDBC连接器构建完整链路。本文围绕Flink在商品实时推荐中的落地实践,拆解数据采集、特征计算、召回排序及避坑排查等关键环节。

weixin_34067102的博客 427

Flink DataStream Joining 完全指南:Window Join 与 Interval Join 实战与原理

本指南聚焦 Apache Flink DataStream API 中两条数据流的连接(Join)能力,系统讲解 Window Join(滚动、滑动、会话窗口三种形态)与 Interval Join 的语义、编程模型与源码级实现原理。读完本文,你将掌握如何为共享 key 且时间上相关的两条流编写正确的连接逻辑,理解内连接语义下的数据取舍规则,并能根据业务场景在窗口连接与间隔连接之间做出合理选择。

gitblog_00311的博客 123

Flink-CEPplus:基于flink 1.8源码二次开发,详见MD

Flink1.8.1-CEPplus 基于Flink1.8.1源码为CEP模块添加逻辑动态注入功能 功能描述: 使用CEP作为复杂事件处理引擎时,当逻辑频繁发生修改,以及阈值频繁调整时 整个程序需要停止后,修改代码,重新打包程序然后给集群提交,无法实现逻辑 动态修改和外部动态注入,目前已经实现了CEP逻辑动态注入,基于消息驱动逻 辑修改,可以手动往source端注入特定消息实现细腻度控制逻辑注入感知 为客户端端API中PatternStream添加方法registerListener(CepListener cepListener)注意必须在选择方法之前调用 cepListener对象需要实现接口 接口方法 Boolean needChange() 每条数据会调用这个方法,用于确定这条数据是否会触发规则更

电网渗透之终端安全

        电力系统安全不仅关系到电网的稳定运行,也关系到国家能源安全和国计民生,甚至关系到国家的安全和利益,电力系统由于结构复杂多样、分布广泛、重要性高,一旦系统瘫痪影响巨大,因此,极容易成为敌对势力攻击的首选目标。随着信息安全暴露面迅速增加,将给公司网络安全防线带来严峻挑战。       监控、保障这些电力系统安全运行变的尤为重要。内部安全防护产品有防火墙、纵向加密、反向隔离设备等...

guapi007008的博客 2721

Apache Flink Hive 读写完全指南:基于 HiveCatalog 的统一批流读写、时态表 Join 与分区提交实战

本指南以当前仓库 [hive_read_write.md](https://link.gitcode.com/i/668e20e2384c06a8edc7e227ce557b4d) 为主体,系统讲解如何通过 `HiveCatalog` 让 Apache Flink 对 Hive 表进行统一的批处理和流处理读写,涵盖流式读取的监控与分区排序机制、以 Hive 表作为时态表(Temporal Tabl

gitblog_00733的博客 189

Easymesh之拓扑模块(二)

介绍 easymesh 拓扑消息:Topo discovery、Topo notification、Topo query、Topo response

qq_53619687的博客 2152

Flink 与 Hive 集成指南:HiveCatalog 元数据管理与 Hive 表读写实战

Apache Hive 早已是数据仓库生态系统的核心,它既是面向大数据分析与 ETL 场景的 SQL 引擎,也是一个用于数据发现、定义与演化的数据管理平台。本指南聚焦 Apache Flink(当前仓库 [flink 项目](https://link.gitcode.com/i/e6bbfddaa877748ae99526698d2e7b6b))与 Hive 的两层集成:其一,利用 Hive Me

gitblog_00943的博客 1020

IEEE Transactions on Industrial Informatics(TII)投稿全流程解析:从准备到成功提交

本文详细解析了向IEEE Transactions on Industrial Informatics(TII)投稿的全流程,涵盖从投稿前的格式准备、内容结构优化到在线提交系统实操等关键环节。重点强调了遵守TII严格的格式规范、双盲评审要求以及如何构建有说服力的学术叙述,旨在帮助研究者提升稿件质量,顺利通过评审。

weixin_28396629的博客 1864

Petalinux 2021.1 + Vivado 2021 实战:手把手教你为Zynq板卡移植Linux并搞定AXI DMA驱动

本文详细介绍了基于Petalinux 2021.1和Vivado 2021工具链,为Zynq开发板移植Linux系统并开发AXI DMA驱动的全流程。从环境配置、硬件设计到驱动适配与性能优化,提供了实战避坑技巧和版本特异性问题的解决方案,帮助开发者快速构建高速数据传输系统。

weixin_42641741的博客 387

Flink Table & SQL API 配置详解:从 TableConfig 到全量配置项实战指南

> **导读**:本文基于 Flink 仓库 [docs/content/docs/dev/table/config.md](https://link.gitcode.com/i/798db87d1b082ea73c0b538ef0e47d0b) 展开,系统讲解 Table & SQL API 的配置体系:如何通过 `EnvironmentSettings`、`Configuration` 与 `

gitblog_07819的博客 962

CentOS7下Ollama部署全攻略:从安装到自定义端口配置(附国内加速技巧)

本文详细介绍了在CentOS7系统上部署Ollama的完整流程,包括环境准备、模型下载优化、服务化部署及端口配置等关键步骤。特别针对国内网络环境提供了加速安装方案和镜像源配置技巧,帮助开发者快速搭建稳定的本地AI运行环境。

mmm90的博客 289

Flink SQL 确定性解析:从批处理到流式查询的非确定性更新(NDU)问题与消除方案

> 本指南围绕 Flink SQL 中“查询确定性”这一核心概念展开,完整讲解什么是确定性、批处理与流处理中非确定性的不同成因,重点剖析流式增量更新场景下由非确定性引发的 NDU(Non-Deterministic Update)问题,并结合 Flink 1.16+ 提供的 `table.optimizer.non-deterministic-update.strategy` 机制与真实案例,给出

gitblog_00779的博客 245

【OpenCV】复杂场景下的高精度圆检测实战(附完整代码)

本文针对OpenCV霍夫圆检测在复杂场景下易失效的问题,提出了一套基于轮廓分析的高精度圆检测实战方案。通过图像预处理、轮廓发现及多轮几何筛选(面积、周长、椭圆拟合、多边形逼近),有效排除噪声和类圆干扰物,显著提升复杂场景下的检测鲁棒性,并附完整可调参的Python代码实现。

weixin_29095587的博客 200

Android11,无障碍服务模拟多手势使用dispatchGesture时总是onCancelled

AccessibilityService的dispatchGesture去模拟多手势,总是onCancelled的一种解决办法

m0_49953943的博客 2102

Flink 技术与应用(一)

是一个开源的大数据处理框架,其起源可以追溯到一个名为 Stratosphere 的研究项目,旨在建立下一代大数据分析引擎,2010 年,从 Stratosphere 项目中分化出了 Flink 的前身。到了 2014 年,Flink 项目被捐赠给了 Apache 软件基金会,并在同年 4 月成为 Apache 的孵化项目,12 月成为 Apache 的顶级项目。

1329

让 ABAP 开发更聪明的搭档:SAP Joule for Developers 与 ABAP AI Capabilities 全面实战

摘要:SAP已将生成式AI集成到ABAP开发工具中,推出Joule for Developers功能。该功能直接嵌入Eclipse开发环境,提供代码解释、生成、测试构造和遗留代码迁移等辅助功能。Joule支持ABAP Cloud项目开发,能围绕当前开发对象提供上下文相关的建议,帮助开发者高效完成应用开发与迁移任务。启用该功能需升级ADT并获取相应许可,典型应用场景包括RAP应用构建和S/4HANA迁移中的代码重构。官方资源提供了多个实践案例,帮助开发者快速上手这一AI辅助开发功能。(149字)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 492

Flink 1.16 版本发布说明与升级指南:从 1.15 迁移的关键变更全解析

本文围绕 Apache Flink 1.16 的官方 Release Notes 展开,系统梳理 Flink 1.15 与 1.16 之间在集群部署、Table API & SQL、连接器、运行时与协调、Checkpoint、Python 以及依赖版本等方面的行为变更。如果你正在规划将 Flink 升级到 1.16,或希望理解当前仓库(`flink` 主干分支)中 1.16 版本能力的实现细节,本

gitblog_00036的博客 266

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Flink SQL 提示(Hints)完全指南:动态表选项、联接提示与状态 TTL 实战详解

SQL 提示(SQL Hints)是 Flink Table API & SQL 中与 SQL 语句一起使用、用于干预执行计划的关键机制,它在查询(Query)粒度上让用户有能力修正 planner 的默认决策。本文基于 Flink 官方文档整理,并结合本仓库中的 planner 源码与测试用例,系统讲解动态表选项(`OPTIONS`)、联接提示(`BROADCAST`/`SHUFFLE_HASH

gitblog_00550的博客 922

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

3 步让 AI 助手变成逆向工程师:REA 逆向技能从接入到首次实战

关键词:REA 逆向工程 · npx rea-agents setup · rea doctor 体检 · APK 反编译取证 REA(reverse-engineer-anything)把 Hopper、Ghidra、JADX 这类分析工具接到你的 AI 编码助手里,让它能直接读原生二进制、JavaScript/Electron 应用、Android APK、.NET 程序集,结论还带着证据。

gitblog_00497的博客 428
上一篇: flinksql 流表转换, 自定义udf/udtf,SQL 内置函数及自定义函数
下一篇: calcite在flink中的二次开发,介绍解析器与优化器
Direction_Wind
博客等级 码龄8年 6438粉丝 102原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Direction_Wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值