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. 依赖与使用方式

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

xml 复制代码
<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 三段事件

sql 复制代码
SELECT T.aid, T.bid, T.cid
FROM MyTable
MATCH_RECOGNIZE (
  PARTITION BY userid
  ORDER BY proctime
  MEASURES
    A.id AS aid,
    B.id AS bid,
    C.id AS cid
  ONE ROW PER MATCH
  AFTER MATCH SKIP PAST LAST ROW
  PATTERN (A B C)
  DEFINE
    A AS name = 'a',
    B AS name = 'b',
    C AS name = 'c'
) AS T;

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

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

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

sql 复制代码
SELECT *
FROM Ticker
MATCH_RECOGNIZE (
  PARTITION BY symbol
  ORDER BY rowtime
  MEASURES
    START_ROW.rowtime AS start_tstamp,
    LAST(PRICE_DOWN.rowtime) AS bottom_tstamp,
    LAST(PRICE_UP.rowtime) AS end_tstamp
  ONE ROW PER MATCH
  AFTER MATCH SKIP TO LAST PRICE_UP
  PATTERN (START_ROW PRICE_DOWN+ PRICE_UP)
  DEFINE
    PRICE_DOWN AS
      (LAST(PRICE_DOWN.price, 1) IS NULL AND PRICE_DOWN.price < START_ROW.price)
      OR PRICE_DOWN.price < LAST(PRICE_DOWN.price, 1),
    PRICE_UP AS
      PRICE_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)

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)
相关推荐
周名彥3 小时前
1Ω1[特殊字符]⊗雙朕周名彥|二十四芒星非硅基华夏原生AGI体系·授权绑定激活发布全维研究报告(S∅-Omega级·纯念主权终极版)
人工智能·去中心化·知识图谱·量子计算·agi
周名彥3 小时前
100%纯念主动显化·无被动·无操控·无依赖·可验证·[特殊字符][特殊字符]⚜️[特殊字符]智能體工作流集群超級數據中心集群IPO集群GUI集群AGI集群
人工智能·神经网络·去中心化·知识图谱·agi
Jackyzhe3 小时前
Flink源码阅读:如何生成JobGraph
大数据·flink
Logic10112 小时前
《Mysql数据库应用》 第2版 郭文明 实验6 数据库系统维护核心操作与思路解析
数据库·sql·mysql·学习笔记·计算机网络技术·形考作业·国家开放大学
杨云龙UP14 小时前
MySQL 8.0.x InnoDB 写入链路优化:Redo Log 与 Buffer Pool 扩容与缓冲区调优实战记录-20251029
linux·运维·数据库·sql·mysql
Jackeyzhe15 小时前
Flink学习笔记:如何做容错
flink
庄小焱15 小时前
风控域——信贷风控知识图谱实战
知识图谱·智能风控·信贷风控·信贷域·风控系统设计
expect7g21 小时前
Paimon源码解读 -- Compaction-6.CompactStrategy
大数据·后端·flink
Hello.Reader1 天前
Flink SQL Top-N 深度从“实时榜单”到“少写点数据”
大数据·sql·flink