在时序数据库的应用实践中,原始数据的存储与查询只是基础能力,越来越多的业务场景要求在数据写入的同时完成实时计算。无论是数据分级存储与智能降采样、预计算加速实时决策,还是异常检测和低延迟告警,都对系统的流式处理能力提出了更高要求。本文将深入解析时序数据库内置的流计算引擎,展示它如何以 SQL 驱动的方式替代传统流处理框架。
传统流计算方案的痛点
在典型的时序数据处理架构中,实现流计算通常需要部署 Kafka 作为数据缓冲层,再接入 Flink 或 Spark Streaming 等流处理框架。这套组合虽然功能强大,但在实际落地中面临诸多挑战:
- 高昂的开发成本:需要编写 Java/Scala 程序,定义复杂的算子链和数据流拓扑
- 繁重的运维负担:Kafka 集群和 Flink 集群各自需要独立的监控、调优和故障恢复机制
- 数据链路冗长:数据从数据库写入到 Kafka,再由 Flink 消费计算,最终结果写回数据库,链路长、延迟高
- 技术栈碎片化:数据存储用一种技术,流计算用另一种,团队需要掌握多套技术体系
对于以时序数据为核心业务的团队而言,如果流计算的需求主要集中在数据变换、聚合和异常检测等常见场景,引入完整的流处理框架往往是过度设计。
内置流计算引擎的核心设计
TDengine 的流计算引擎采用了一种极简而强大的设计理念:使用 SQL 定义实时流变换。当数据被写入流的源表后,数据会被以定义的方式自动处理,并根据定义的触发模式向目的表推送结果。在高吞吐数据写入下,系统能够提供毫秒级的计算结果延迟。
这种 SQL 驱动的方式带来了显著的优势:
- 低学习成本:熟悉 SQL 的开发人员即可上手,无需学习新的流处理编程模型
- 声明式定义:用 SQL 描述”要计算什么”,而非”如何计算”,引擎自动优化执行计划
- 与存储无缝集成:计算结果直接写入数据库中的目标表,无需跨系统数据搬运
三大核心扩展能力
与简单的连续查询不同,内置流计算引擎在三个维度上进行了深度扩展,使其能够覆盖更广泛的业务场景。
1. 处理对象的扩展:触发与计算分离
在传统流计算中,触发计算的数据源和参与计算的数据源通常是同一个。而内置流计算引擎支持触发与计算分离——触发表与计算的数据源表可以不相同。
例如,可以配置为:当表 A 写入新数据时触发计算,但计算的数据来源是表 B。这种解耦设计使得业务可以灵活定义计算逻辑的触发条件,而不受数据来源的限制。
2. 触发方式的扩展:多种窗口与过滤
引擎支持丰富的触发方式,满足不同时间语义的业务需求:
- 窗口触发:基于固定时间窗口或滑动窗口触发计算
- 定时触发:按固定时间间隔触发,适合周期性统计报表
- 会话窗口触发:基于活动间隔划分会话,适用于用户行为分析
- 状态窗口触发:根据数据状态变化划分窗口
- 事件窗口触发:由特定事件驱动计算
- 计数窗口触发:按数据条数达到阈值触发
此外,系统支持对触发数据进行预先过滤(PRE_FILTER),在数据进入计算逻辑之前就剔除无关记录,减少不必要的计算开销。
3. 计算范围的扩展:跨表跨库计算
流计算既可以对触发表本身进行计算,也可以对其他库表的数据进行计算。更重要的是,它支持任何合法的查询语句,包括聚合、关联、标量计算等,赋予了业务极大的表达自由度。
触发动作的灵活配置
计算完成后,结果的输出方式同样灵活,支持三种触发动作:
- 只通知不计算:通过 WebSocket 推送通知,适合轻量级的实时告警场景
- 只计算不通知:将计算结果写入输出表,适合预聚合和数据降采样
- 既通知又计算:同时推送通知并写入结果表,适合需要即时响应且需要持久化结果的场景
关键控制选项
流计算引擎提供了丰富的控制参数,帮助开发者精细调优计算行为:
| 参数 | 说明 |
|---|---|
| WATERMARK | 定义数据延迟容忍度,处理乱序数据 |
| EXPIRED_TIME | 窗口过期时间,控制计算结果的保留周期 |
| IGNORE_DISORDER | 是否忽略乱序数据 |
| DELETE_OUTPUT_TABLE | 是否在流删除时自动清理输出表 |
| FILL_HISTORY | 是否对流创建前的历史数据进行回填计算 |
| LOW_LATENCY_CALC | 启用低延迟计算模式 |
| PRE_FILTER | 触发数据的预过滤条件 |
| MAX_DELAY | 最大允许延迟,平衡延迟与吞吐 |
其中,WATERMARK 和 IGNORE_DISORDER 是处理工业场景中常见的数据乱序问题的关键参数。在设备网络不稳定、数据上报延迟差异较大的情况下,合理配置这两个参数可以有效避免因乱序数据导致的计算结果不准确。
FILL_HISTORY 选项则解决了流计算的一个常见痛点:流创建之前的历史数据是否需要纳入计算。启用该选项后,引擎会对历史数据进行回填,确保计算结果的完整性。
高可用架构:存算分离与负载均衡
在生产环境中,流计算任务的高可用性至关重要。内置流计算引擎支持流的存算分离架构:
- snode(Stream Node):负责运行流计算任务,是独立的计算节点
- 多 snode 负载均衡:多个 snode 之间自动分配流计算任务,避免单点过载
- 互为副本:snode 之间互为副本,当某个节点故障时,其他节点自动接管其计算任务
这种架构设计使得流计算能力可以独立于存储节点进行水平扩展,根据计算负载的变化灵活调整 snode 数量,同时保证计算任务的持续可用。
连续异常检测
异常检测是工业互联网场景中的核心需求之一。流计算引擎支持通过调用异常检测服务实现连续异常检测,使用 ANOMALY_WINDOW 函数对数据流进行实时异常分析。
具体而言,可以在流计算的定义中嵌入异常检测逻辑,当数据流经计算管道时,自动对指定窗口内的数据进行异常评分或分类。结合前面提到的 WebSocket 通知机制,一旦检测到异常,可以立即推送告警,实现端到端的实时异常响应。
与传统方案对比
| 维度 | 内置流计算 | Kafka + Flink |
|---|---|---|
| 定义方式 | SQL | Java/Scala 程序 |
| 部署组件 | 仅数据库 | Kafka + Flink + 数据库 |
| 运维复杂度 | 低 | 高 |
| 数据链路 | 数据库内部 | 跨系统 |
| 学习成本 | SQL 即可 | 需掌握流处理框架 |
| 结果存储 | 直接写入库表 | 需要回写数据库 |
需要指出的是,内置流计算引擎并非要替代所有场景下的 Kafka + Flink 方案。对于需要复杂事件处理(CEP)、多流 Join、跨异构数据源等高级需求的场景,传统流处理框架仍然有其优势。但对于以时序数据为核心、计算逻辑以聚合和变换为主的典型物联网和工业场景,内置流计算引擎在简洁性和效率上具有明显优势。
结语
流计算是时序数据处理从”存得好”迈向”算得快”的关键一步。TDengine 的流计算引擎以 SQL 为核心接口,通过触发与计算分离、多种窗口类型、跨表跨库计算等扩展能力,覆盖了物联网和工业互联网场景中的主流流计算需求。结合存算分离的高可用架构和毫秒级计算延迟,这套方案能够在不增加系统复杂度的前提下,为企业提供生产级的实时计算能力。

























