RuleGo RuleGo
🏠首页
  • 快速入门
  • 规则链
  • 标准组件
  • 扩展组件
  • 自定义组件
  • 可视化
  • RuleGo-Server
  • AOP
  • 触发器
  • 高级主题
  • 性能
  • 标准组件
  • 扩展组件
  • 自定义组件
  • 流式计算
  • 组件市场
  • 概述
  • 快速入门
  • 路由
  • DSL
  • API
  • Options
  • 组件
🔥编辑器 (opens new window)
  • 可视化编辑器 (opens new window)
  • RuleGo-Server (opens new window)
  • 🌊StreamSQL
  • 🤖智能体框架
  • 🦀TPCLAW 智能体平台 (opens new window)
  • ❓问答

    • FAQ
💖支持
👥加入社区
  • Github (opens new window)
  • Gitee (opens new window)
  • GitCode (opens new window)
  • 更新日志 (opens new window)
  • English
  • 简体中文
🏠首页
  • 快速入门
  • 规则链
  • 标准组件
  • 扩展组件
  • 自定义组件
  • 可视化
  • RuleGo-Server
  • AOP
  • 触发器
  • 高级主题
  • 性能
  • 标准组件
  • 扩展组件
  • 自定义组件
  • 流式计算
  • 组件市场
  • 概述
  • 快速入门
  • 路由
  • DSL
  • API
  • Options
  • 组件
🔥编辑器 (opens new window)
  • 可视化编辑器 (opens new window)
  • RuleGo-Server (opens new window)
  • 🌊StreamSQL
  • 🤖智能体框架
  • 🦀TPCLAW 智能体平台 (opens new window)
  • ❓问答

    • FAQ
💖支持
👥加入社区
  • Github (opens new window)
  • Gitee (opens new window)
  • GitCode (opens new window)
  • 更新日志 (opens new window)
  • English
  • 简体中文

广告采用随机轮播方式显示 ❤️成为赞助商
  • 概述
  • 快速开始
  • 核心概念
  • SQL参考
  • API参考
  • RuleGo集成
  • 加入社区讨论
  • Schema 校验
  • 分析函数
  • 进阶示例
  • 模式识别(MATCH_RECOGNIZE / CEP)
  • 函数

  • 案例集锦

    • 案例集锦概述
    • 流表 JOIN 元数据增强
    • 会话窗口与设备在线分析
    • 变更数据捕获案例
    • 滑动窗口与持续检测
    • 数据过滤与转换
    • IoT 温度告警与指标聚合
    • 设备故障模式识别(MATCH_RECOGNIZE)
      • 场景 A:连续越限防抖(A{3})
        • 业务目标
        • SQL
        • 输入与输出
        • 行为说明
      • 场景 B:升温后骤降(故障前兆,A+ B)
        • 业务目标
        • SQL
        • 输入与输出
        • 行为说明
      • 场景 C:振动突发(A{5,})
        • 业务目标
        • SQL
        • 输入与输出
        • 行为说明
      • 场景 D:开停机工作流(跨事件类型序列)
        • 业务目标
        • SQL
        • 输入与输出
        • 行为说明
      • 场景 E:乱序鉴权(PERMUTE,任意顺序)
        • 业务目标
        • SQL
        • 输入与输出
        • 行为说明
      • 场景 F:时间约束确认(WITHIN)
        • 业务目标
        • SQL
        • 输入与输出
        • 行为说明
      • 场景对比一览
      • 📚 相关文档
目录

设备故障模式识别(MATCH_RECOGNIZE)

# 设备故障模式识别案例

物联网 / 工业场景里,很多告警不是"单点越限",而是一组按特定顺序出现的事件——连续几次超阈值、升温后骤降、开机→运行→停机的工作流、突发振动。这类"事件序列模式"正是 MATCH_RECOGNIZE(模式识别 / CEP)的用武之地。

本案例围绕一个设备读数流 stream,串联六个子场景,覆盖模式识别最常用的几种形态:

子场景 模式 核心能力
A. 连续越限防抖 A{3} 固定次数重复——避免单点抖动误报
B. 升温后骤降(故障前兆) A+ B 量词 + 序列——持续态后转态
C. 振动突发 A{5,} 下限重复——高频突发检测
D. 开停机工作流 Start Running Stop 跨事件类型序列
E. 乱序鉴权 PERMUTE(A, B) 任意顺序——不关心先后
F. 时间约束确认 A B ... WITHIN 时间窗——必须在 N 秒内完成

如何运行这些 SQL

本文每个场景只给 SQL + 输入 + 输出;运行方式见案例集锦 · 如何运行案例 SQL。模式识别查询必须用 Emit + AddSink(EmitSync 不支持 MATCH_RECOGNIZE);想保序用 AddSyncSink。

# 场景 A:连续越限防抖(A{3})

# 业务目标

温度偶尔抖动到高值是正常的(电磁干扰、采样毛刺)。只有连续 3 次都越过 80°C 才认定真实过热并告警,避免单点抖动误报。每个设备各自计数(PARTITION BY deviceId)。

# SQL

SELECT * FROM stream
MATCH_RECOGNIZE (
    PARTITION BY deviceId ORDER BY ts
    MEASURES MATCH_NUMBER() AS mn, COUNT(*) AS hits, LAST(A.temp) AS peak
    ONE ROW PER MATCH
    PATTERN (A{3})
    WITHIN '1h'
    DEFINE A AS temp > 80
)
1
2
3
4
5
6
7
8
9

# 输入与输出

dev-01 连续三次超 80 构成一次匹配;dev-02 只有两次,不够 3 次:

{"deviceId": "dev-01", "ts": 1, "temp": 60}
{"deviceId": "dev-01", "ts": 2, "temp": 82}
{"deviceId": "dev-01", "ts": 3, "temp": 85}
{"deviceId": "dev-01", "ts": 4, "temp": 88}
{"deviceId": "dev-02", "ts": 5, "temp": 90}
{"deviceId": "dev-02", "ts": 6, "temp": 91}
1
2
3
4
5
6

输出(dev-01 第 2–4 条构成 A{3}):

[alert] {deviceId:dev-01 mn:1 hits:3 peak:88}
1

# 行为说明

  • PATTERN (A{3}):A 连续重复恰好 3 次;中间出现一个不满足 temp>80 的行就打断,需重新凑满 3 次。
  • PARTITION BY deviceId:每个设备各自的匹配,dev-02 的两次不会被算进 dev-01。
  • COUNT(*) 数 A 的行数(这里恒为 3),LAST(A.temp) 取最后一次温度作为峰值。
  • 默认 AFTER MATCH SKIP PAST LAST ROW:匹配不重叠,下一次从本次最后一行之后找起。

# 场景 B:升温后骤降(故障前兆,A+ B)

# 业务目标

设备故障前常见"持续高温运行 → 温度骤降"的形态(如冷却液突然失效、传感器脱开)。识别"连续多行高温后,紧接着一行回落到低温"。

# SQL

SELECT * FROM stream
MATCH_RECOGNIZE (
    PARTITION BY deviceId ORDER BY ts
    MEASURES MATCH_NUMBER() AS mn, MAX(A.temp) AS peak, B.temp AS drop_to
    ONE ROW PER MATCH
    PATTERN (A+ B)
    WITHIN '1h'
    DEFINE
        A AS temp > 80,
        B AS temp < 30
)
1
2
3
4
5
6
7
8
9
10
11

# 输入与输出

dev-01 高温 3 行后骤降到 25:

{"deviceId": "dev-01", "ts": 1, "temp": 85}
{"deviceId": "dev-01", "ts": 2, "temp": 90}
{"deviceId": "dev-01", "ts": 3, "temp": 95}
{"deviceId": "dev-01", "ts": 4, "temp": 25}
1
2
3
4

输出:

[alert] {deviceId:dev-01 mn:1 peak:95 drop_to:25}
1

# 行为说明

  • A+(贪婪,至少 1 次):持续吃掉 temp>80 的行,尽可能多匹配;B 吃第一个 temp<30 的行。
  • 整个匹配 [85,90,95,25]:A = 前三行,B = 25 那行。
  • MAX(A.temp) 聚合 A 段最高温,B.temp 取 B 行的温度(符号限定字段取该符号最后一次出现)。
  • 若高温段后没有回落(一直高温到流末),匹配未闭合,Stop 时经 Flush 才产出(贪婪等延伸终止)。

# 场景 C:振动突发(A{5,})

# 业务目标

振动传感器在设备失衡时高频抖动。识别"至少连续 5 次"振幅超阈值的突发段(A{5,} = 5 次及以上)。

# SQL

SELECT * FROM stream
MATCH_RECOGNIZE (
    PARTITION BY deviceId ORDER BY ts
    MEASURES MATCH_NUMBER() AS mn, COUNT(*) AS bursts, MAX(A.amp) AS max_amp
    ONE ROW PER MATCH
    PATTERN (A{5,})
    WITHIN '1h'
    DEFINE A AS amp > 50
)
1
2
3
4
5
6
7
8
9

# 输入与输出

dev-01 连续 6 次高振幅后回落(突发段 ≥5,匹配);末尾 amp=40 不满足 A,结束这段突发并触发输出:

{"deviceId": "dev-01", "ts": 1, "amp": 60}
{"deviceId": "dev-01", "ts": 2, "amp": 65}
{"deviceId": "dev-01", "ts": 3, "amp": 70}
{"deviceId": "dev-01", "ts": 4, "amp": 62}
{"deviceId": "dev-01", "ts": 5, "amp": 68}
{"deviceId": "dev-01", "ts": 6, "amp": 71}
{"deviceId": "dev-01", "ts": 7, "amp": 40}
1
2
3
4
5
6
7

输出:

[alert] {deviceId:dev-01 mn:1 bursts:6 max_amp:71}
1

# 行为说明

  • A{5,}(贪婪):至少 5 次,尽量多匹配。dev-01 的 6 次全部进入一个匹配。
  • 贪婪量词没有自然终点时,匹配会延伸到下一个不满足 A 的行(这里的 amp=40)才产出、选最长;若一直满足到流末,则在 Stop 时经 Flush 产出。少于 5 次的突发段(如下方只有 4 次的情形)不产出。
  • 突发段中间只要有一行 amp≤50 就打断;AFTER MATCH SKIP PAST LAST ROW 后从断点之后重新累计。

# 场景 D:开停机工作流(跨事件类型序列)

# 业务目标

设备的生命周期事件用 type 字段区分(start/running/stop)。识别完整的"开机 → 运行 → 停机"序列,统计该周期的运行峰值。每个符号匹配不同的 type。

# SQL

SELECT * FROM stream
MATCH_RECOGNIZE (
    PARTITION BY deviceId ORDER BY ts
    MEASURES MATCH_NUMBER() AS cycle, MAX(Running.power) AS peak_power
    ONE ROW PER MATCH
    PATTERN (Start Running+ Stop)
    WITHIN '24h'
    DEFINE
        Start   AS type == "start",
        Running AS type == "running",
        Stop    AS type == "stop"
)
1
2
3
4
5
6
7
8
9
10
11
12

# 输入与输出

dev-01 一个完整周期:start → 两行 running → stop:

{"deviceId": "dev-01", "ts": 1, "type": "start",   "power": 0}
{"deviceId": "dev-01", "ts": 2, "type": "running", "power": 120}
{"deviceId": "dev-01", "ts": 3, "type": "running", "power": 150}
{"deviceId": "dev-01", "ts": 4, "type": "stop",    "power": 0}
1
2
3
4

输出:

[cycle] {deviceId:dev-01 cycle:1 peak_power:150}
1

# 行为说明

  • 每个符号用 type == "..." 匹配不同事件(字符串相等用 ==)。
  • Running+:运行态可以持续多行,MAX(Running.power) 取运行段峰值。
  • WITHIN '24h':一个开停机周期不应跨天;超窗的部分匹配被主动清理,避免"开了机一直没停"的事件永远挂留。
  • 符号名区分大小写,建议用有意义的名字(Start/Running/Stop)提升可读性。

# 场景 E:乱序鉴权(PERMUTE,任意顺序)

# 业务目标

安全审计要求"一次会话里既出现登录(login)又出现鉴权(auth)",但两者先后无所谓(有的客户端先 auth 再 login)。用 PERMUTE 匹配任意顺序。

# SQL

SELECT * FROM stream
MATCH_RECOGNIZE (
    PARTITION BY sessionId ORDER BY ts
    MEASURES MATCH_NUMBER() AS mn, FIRST(Login.ts) AS t1, FIRST(Auth.ts) AS t2
    ONE ROW PER MATCH
    PATTERN (PERMUTE(Login, Auth))
    WITHIN '10m'
    DEFINE
        Login AS event == "login",
        Auth  AS event == "auth"
)
1
2
3
4
5
6
7
8
9
10
11

# 输入与输出

会话 s1 先 login 后 auth;会话 s2 先 auth 后 login——两者都匹配:

{"sessionId": "s1", "ts": 1, "event": "login"}
{"sessionId": "s1", "ts": 2, "event": "auth"}
{"sessionId": "s2", "ts": 3, "event": "auth"}
{"sessionId": "s2", "ts": 4, "event": "login"}
1
2
3
4

输出:

[audit] {sessionId:s1 mn:1 t1:1 t2:2}
[audit] {sessionId:s2 mn:1 t1:4 t2:3}
1
2

# 行为说明

  • PERMUTE(Login, Auth) 等价于 (Login Auth) | (Auth Login),两个符号的任意顺序都算匹配。
  • PARTITION BY sessionId:每个会话各自识别。
  • FIRST(Login.ts) / FIRST(Auth.ts):取该符号第一次出现的时间戳,可据此判断实际先后。
  • 符号多时 PERMUTE 编译为全排列(N!),边缘通常 2–3 个符号。

# 场景 F:时间约束确认(WITHIN)

# 业务目标

告警产生后,运维必须在 30 秒内确认(ack)。识别"告警事件后 30 秒内出现确认事件"——超时则匹配失败(告警未被及时处理)。这依赖 WITHIN 时间窗。

# SQL

SELECT * FROM stream
MATCH_RECOGNIZE (
    PARTITION BY deviceId ORDER BY ts
    MEASURES MATCH_NUMBER() AS mn, Alert.ts AS alert_at, Ack.ts AS ack_at
    ONE ROW PER MATCH
    PATTERN (Alert Ack)
    WITHIN '30s'
    DEFINE
        Alert AS event == "alert",
        Ack   AS event == "ack"
)
1
2
3
4
5
6
7
8
9
10
11

ts 用毫秒级 epoch 时间戳(WITH (TIMESTAMP='ts', TIMEUNIT='ms') 语义,MATCH_RECOGNIZE 的 ORDER BY 字段自动判单位归一化)。

# 输入与输出

dev-01 告警后 10 秒确认(匹配);dev-02 告警后 60 秒才确认(超 30 秒窗,匹配未完成、被过期清理):

{"deviceId": "dev-01", "ts": 1700000000000, "event": "alert"}
{"deviceId": "dev-01", "ts": 1700000010000, "event": "ack"}
{"deviceId": "dev-02", "ts": 1700000020000, "event": "alert"}
{"deviceId": "dev-02", "ts": 1700000080000, "event": "ack"}
1
2
3
4

输出:

[ok] {deviceId:dev-01 mn:1 alert_at:1700000000000 ack_at:1700000010000}
1

# 行为说明

  • WITHIN '30s':Alert 到 Ack 必须在 30 秒内。dev-01 间隔 10 秒 ✓;dev-02 间隔 60 秒 ✗。
  • dev-02 的部分匹配(Alert 已匹配、等 Ack)在超过 30 秒后由后台 sweeper 主动清理——不必等 Ack 事件到达才判定,空闲分区的超窗状态不会挂留。
  • 未在窗内完成的告警不产出(可另配一条规则统计"未及时确认")。
  • ts 用 epoch 量级(秒/毫秒/微秒/纳秒)才会触发 wall-clock 主动过期;用小值序号(1,2,3…)时维持纯被动(事件到达时检查)。

# 场景对比一览

场景 模式骨架 关键子句 解决什么
A 防抖 A{3} 固定次数 单点抖动误报
B 故障前兆 A+ B 贪婪量词 + 序列 持续态后转态
C 突发 A{5,} 下限次数 高频重复段
D 工作流 Start Running+ Stop 跨类型 + 量词 生命周期序列
E 乱序 PERMUTE(A, B) 排列 先后无所谓
F 时间约束 A B WITHIN 时间窗 + 主动过期 必须 N 秒内

# 📚 相关文档

  • 模式识别(MATCH_RECOGNIZE) —— 完整语法参考(PATTERN / DEFINE / MEASURES / 导航 / 聚合 / SUBSET / FINAL-RUNNING / SKIP)
  • 如何运行案例 SQL —— 统一的 Go 运行样板
  • 分析函数 —— 相邻两事件的变化检测(lag/had_changed),与 CEP 互补
在 GitHub 上编辑此页 (opens new window)
上次更新: 2026/07/14, 04:03:16
IoT 温度告警与指标聚合

← IoT 温度告警与指标聚合

Theme by Vdoing | Copyright © 2023-2026 RuleGo Team | Apache 2.0 License

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式