news 2026/5/6 11:12:04

Flink SQL 模式识别用 MATCH_RECOGNIZE 把 CEP 写成 SQL

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flink SQL 模式识别用 MATCH_RECOGNIZE 把 CEP 写成 SQL

1. 为什么要用 MATCH_RECOGNIZE

在流式场景里,“找一段事件序列模式”是高频需求:比如A→B→C的业务链路、连续下降后反弹的价格走势、登录失败多次后成功等。

Flink 本身有 CEP(Complex Event Processing)库用于模式检测,同时 Flink SQL 也提供了更“关系化”的表达方式:用MATCH_RECOGNIZE在 SQL 里描述复杂事件模式。Flink 文档明确指出:该能力内部基于 Flink CEP 实现,并且 Flink 的MATCH_RECOGNIZE是 SQL 行模式识别标准能力的一部分子集。(Apache Nightlies)

标准背景:SQL 的行模式识别(Row Pattern Recognition)在 SQL:2016 进入标准体系,ISO/IEC 19075-5 对其语义与语法做了规范(包括MATCH_RECOGNIZE)。(國際標準組織)

2. 依赖与使用方式

2.1 在 Maven 工程中使用(需要引入 flink-cep)

Flink 文档说明:要在工程里用MATCH_RECOGNIZE,需要把flink-cep加到依赖里。(Apache Nightlies)

<dependency><groupId>org.apache.flink</groupId><artifactId>flink-cep</artifactId><version>2.2.0</version></dependency>

版本建议:和你集群/依赖的 Flink 主版本保持一致(上面示例是 2.2.0)。(Maven Central)

2.2 SQL Client 里用(通常不需要额外操作)

Flink 文档也提到:在 Flink SQL Client 中使用MATCH_RECOGNIZE,默认依赖已包含。(Apache Nightlies)

3. MATCH_RECOGNIZE 语法骨架:7 个核心子句

一条MATCH_RECOGNIZE查询通常由以下子句组成:(Apache Nightlies)

  1. PARTITION BY:按键分区(类似聚合的 group by 语义)
  2. ORDER BY:指定事件顺序(模式依赖顺序)
  3. MEASURES:定义输出字段(类似 select)
  4. ONE ROW PER MATCH:每次匹配输出几行(Flink 重点支持这一种)(Apache Nightlies)
  5. AFTER MATCH SKIP:控制下一次匹配从哪开始(避免/允许重叠匹配)(Apache Nightlies)
  6. PATTERN:用“类正则”表达模式(A B C、A B+ C* 等)(Apache Nightlies)
  7. DEFINE:定义模式变量 A/B/C 各自满足的条件(Apache Nightlies)

4. 非常关键的 SQL 语义与限制(不看会踩坑)

4.1 只能作用在 Append 表,并且输出也是 Append 表

Flink 文档明确写了 “Attention”:MATCH_RECOGNIZE只能应用到 append table,并且结果也始终是 append table。(Apache Nightlies)

这意味着:

  • 如果你的上游是更新流(Upsert/Changelog),直接用可能不被支持;
  • 结果下游一般按 append sink 思路处理(不依赖更新/撤回语义)。

4.2 强烈建议写 PARTITION BY,否则可能退化成非并行算子

如果不分区,为了保证全局有序,MATCH_RECOGNIZE可能会被翻译成非并行算子(性能直接崩)。Flink 文档对此有明确建议:强烈建议 partition incoming data。(Apache Nightlies)

4.3 ORDER BY 的第一排序键必须是时间属性且升序

Flink 解释了 ORDER BY 的约束:它假定ORDER BY的第一个参数是time attribute 且 ASC;比如ORDER BY rowtime ASC, price DESC可以,但ORDER BY price, rowtimeORDER BY rowtime DESC, ...不行。(Apache Nightlies)

5. 一个“最小可用”示例:匹配 A→B→C 三段事件

SELECTT.aid,T.bid,T.cidFROMMyTable MATCH_RECOGNIZE(PARTITIONBYuseridORDERBYproctime MEASURES A.idASaid,B.idASbid,C.idAScid ONEROWPERMATCHAFTERMATCHSKIP PASTLASTROWPATTERN(A B C)DEFINE AASname='a',BASname='b',CASname='c')AST;

这一类写法的价值:把原来 CEP 里的状态机逻辑,直接用 SQL 的“模式变量 + 类正则 PATTERN + 规则 DEFINE”写出来。(Apache Nightlies)

6. 实战例子:识别“持续下跌后反弹”的股票价格区间

Flink 官方示例:找出某个股票价格连续下降(一个或多个 PRICE_DOWN),最后出现一次PRICE_UP的区间,并输出区间起点、最低点、终点。(Apache Nightlies)

SELECT*FROMTicker MATCH_RECOGNIZE(PARTITIONBYsymbolORDERBYrowtime MEASURES START_ROW.rowtimeASstart_tstamp,LAST(PRICE_DOWN.rowtime)ASbottom_tstamp,LAST(PRICE_UP.rowtime)ASend_tstamp ONEROWPERMATCHAFTERMATCHSKIPTOLASTPRICE_UP PATTERN(START_ROW PRICE_DOWN+PRICE_UP)DEFINE PRICE_DOWNAS(LAST(PRICE_DOWN.price,1)ISNULLANDPRICE_DOWN.price<START_ROW.price)ORPRICE_DOWN.price<LAST(PRICE_DOWN.price,1),PRICE_UPASPRICE_UP.price>LAST(PRICE_DOWN.price,1))MR;

你可以重点学这 3 个技巧:

  1. PRICE_DOWN++表示至少一次(类正则量词)(Apache Nightlies)
  2. LAST(var.col, 1):在 DEFINE 中引用“上一个满足该变量条件的行”做对比(实现“越来越小/越来越大”)(Apache Nightlies)
  3. AFTER MATCH SKIP TO LAST PRICE_UP:控制下一次匹配从哪里开始,避免一次下跌区间被过度拆分/重叠 (Apache Nightlies)

7. 已知限制:Flink 只是标准子集(常见不支持点)

Flink 文档的 Known Limitations 中明确提到一些 SQL 标准里的模式表达能力当前不支持,例如:(Apache Nightlies)

  • Pattern groups:不能对一个子序列整体加量词,比如(A (B C)+)不合法
  • Alterations:不支持|这种分支模式,如PATTERN((A B | C D) E)

此外还有一个非常实用的提醒:MATCH_RECOGNIZE不会使用你配置的 state retention time,如果你担心状态无限增长,需要用WITHIN来限制匹配窗口。(Apache Nightlies)

8. 生产建议清单(直接照做,少走弯路)

  1. 一定写PARTITION BY(按 userId / deviceId / symbol 等),避免退化成非并行全局排序。(Apache Nightlies)
  2. ORDER BY第一列用时间属性且 ASC,必要时第二列再按业务字段辅助排序。(Apache Nightlies)
  3. AFTER MATCH SKIP ...明确你的“是否允许重叠匹配”的策略。(Apache Nightlies)
  4. 模式可能长时间不闭合时,用WITHIN控状态,否则状态可能积压。(Apache Nightlies)
  5. 记住它只能吃 append 表、产出 append 表,链路上游/下游要匹配这个语义。(Apache Nightlies)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/2 14:31:56

Flink SQL Time Travel用 FOR SYSTEM_TIME AS OF 查询历史快照

1. Time Travel 是什么&#xff0c;能解决什么问题 Time Travel&#xff08;时间旅行&#xff09;用于查询表在某个历史时间点的“数据与表结构状态”。你可以指定一个时间点&#xff0c;让 Flink 返回该时间点对应的表数据&#xff0c;适合做&#xff1a; 历史对账、回溯分析…

作者头像 李华
网站建设 2026/4/24 7:01:59

36、脚本编程中的参数、循环与数据处理

脚本编程中的参数、循环与数据处理 1. 位置参数 位置参数在脚本编程中是非常重要的概念,它们允许我们在执行脚本时传递参数。以下是不同形式的位置参数及其结果: | 形式 | 结果 | | ---- | ---- | | $1 = word $2 = words $3 = with $4 = spaces | 原始位置参…

作者头像 李华
网站建设 2026/4/30 0:49:06

Arduino UNO Q 烘托圣诞节气氛

本示例将传统LED控制升级为沉浸式节日体验&#xff0c;基于Arduino UNO Q开发。系统包含交互式圣诞树、音乐播放器和实时视觉反馈。通过简单的网络用户界面来切换板载 LED 的状态。应用程序通过网络浏览器监听用户输入并相应地更新 LED 状态。它展示了如何在 Linux 环境中与硬件…

作者头像 李华
网站建设 2026/5/5 1:32:16

【思维模型】第一性原理 ③ ( 5 Why 分析法 | 明确问题 | 层层深入 | 验证原因 | 改进措施 )

文章目录一、5 Why 分析法1、概念简介2、核心原则3、实施步骤4、关键技巧5、常见误区6、案例分析在 【思维模型】第一性原理 ② ( 利用 “ 第一性原理 “ 进行创新 : 归零 -&#xff1e; 解构 -&#xff1e; 重构 | 跨学科学习 ) 博客中 , 屡次提到了 5 Why 分析法 , 本篇博客简…

作者头像 李华
网站建设 2026/5/5 20:18:32

AI:深度学习的前向传播和反向传播

深度学习的前向传播和反向传播是神经网络训练的核心机制&#xff0c;前者负责生成预测结果&#xff0c;后者负责根据误差优化模型参数&#xff0c;二者共同构成一个完整的训练迭代循环。 一、前向传播&#xff08;Forward Propagation&#xff09; 前向传播是神经网络从输入到输…

作者头像 李华
网站建设 2026/5/4 4:50:20

33、GnomeVFS:GNOME 应用的虚拟文件系统

GnomeVFS:GNOME 应用的虚拟文件系统 1. GnomeVFS 概述 GnomeVFS 是一个为 GNOME 应用程序提供虚拟文件系统的库和模块集。相较于系统的原生文件系统,使用虚拟抽象文件系统有诸多好处。除了抽象化带来的可移植性外,GnomeVFS 还将文件系统的访问范围扩展到了本地磁盘之外。例…

作者头像 李华