分类 :8.预聚合 | 篇章 :02 TSMA
适用版本:TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-07-07
TSMA(Time-Range SMA)是 RSMA 之外的另一种预聚合方式,类似于关系数据库的物化视图。用户为某超级表显式创建 TSMA,指定聚合函数和时间间隔,查询时引擎自动判断命中。
核心概念速查表
| 概念 | 说明 |
|---|---|
| TSMA | Time-Range SMA |
| INTERVAL | TSMA 的聚合粒度 |
| Func | 预聚合的函数列表 |
| Auto Maintenance | 写入时自动维护 |
| Query Routing | 查询自动路由 |
详细解析
1. TSMA 与 RSMA 对比
RSMA:
- 数据库级配置
- 固定 3 层
- 仅 ROLLUP 函数
- 数据按 RETENTIONS 自动过期
- 建库时定义
TSMA:
- 表级配置
- 任意数量 TSMA
- 任意聚合函数
- 与超级表共享生命周期
- 任意时刻 CREATE/DROP
典型场景:
RSMA: 大规模时序,需要分层存储
TSMA: 已有超级表,针对特定聚合需求加速
2. 创建 TSMA
sql
-- 基础语法
CREATE TSMA tsma_name
ON super_table_name
FUNCTION(func1, func2, ...)
INTERVAL(duration);
-- 示例:电流的多个聚合
CREATE TSMA meters_1h
ON meters
FUNCTION(AVG(current), MAX(current), MIN(current), COUNT(*))
INTERVAL(1h);
效果:
- TDengine 后台为 meters 维护 1 小时粒度的预聚合
- 查询 AVG/MAX/MIN/COUNT 时优先用 TSMA
3. 多 TSMA 共存
sql
-- 多层 TSMA
CREATE TSMA meters_5m ON meters
FUNCTION(AVG(current), MAX(current))
INTERVAL(5m);
CREATE TSMA meters_1h ON meters
FUNCTION(AVG(current), MAX(current), SUM(voltage))
INTERVAL(1h);
CREATE TSMA meters_1d ON meters
FUNCTION(AVG(current), MAX(current))
INTERVAL(1d);
查询时自动选择:
-- 命中 1m 粒度查询 → 用 meters_5m
SELECT _wstart, AVG(current) FROM meters
WHERE ts > now-1h INTERVAL(5m);
-- 命中 1h 粒度查询 → 用 meters_1h
SELECT _wstart, AVG(current) FROM meters
WHERE ts > now-7d INTERVAL(1h);
-- 命中 1d 粒度查询 → 用 meters_1d
SELECT _wstart, AVG(current) FROM meters
WHERE ts > now-1y INTERVAL(1d);
最优 TSMA 选择算法:
① 找出粒度 ≤ 查询 INTERVAL 的所有 TSMA
② 在其中选最大粒度(覆盖最多数据)
③ 必须包含查询所需的所有函数
4. TSMA 的自动维护
写入时维护:
① 应用 INSERT 数据
② 写入原始数据
③ 异步触发 TSMA 更新:
- 找到对应窗口
- 增量更新聚合状态
- 持久化
查询时优化:
① Parser 识别查询
② Optimizer 评估可用 TSMA
③ 选择最优 TSMA
④ 重写查询计划
⑤ 执行
窗口归属:
数据 ts=12:34:56
→ 5 分钟 TSMA:归属 [12:30, 12:35)
→ 1 小时 TSMA:归属 [12:00, 13:00)
5. TSMA 命中条件
查询命中 TSMA 的必要条件:
① INTERVAL 是 TSMA INTERVAL 的整数倍:
TSMA 5m 可命中 SQL INTERVAL 5m/10m/15m/1h
不可命中 INTERVAL 3m
② 查询的聚合函数在 TSMA 函数列表中:
TSMA FUNCTION(AVG, MAX) → 可命中 AVG/MAX
不可命中 SUM(未预聚合)
③ 时间范围对齐:
查询时间范围最好整窗口对齐
部分窗口可能需要原始数据补充
④ WHERE 条件兼容:
仅 Tag 过滤 → 可命中
数据列过滤 → 通常无法命中
用 EXPLAIN 检查是否命中:
EXPLAIN SELECT _wstart, AVG(current) FROM meters
WHERE ts > now-7d INTERVAL(1h);
→ 查找 "TSMA Scan" 节点表明命中
6. TSMA 与 PARTITION BY
sql
-- TSMA 是否考虑 PARTITION BY?
-- 答:默认 TSMA 按超级表全局聚合
-- 如需按子表,需要 SELECT 中加入 tbname / Tag
-- 推荐场景:全表聚合
CREATE TSMA meters_global_1h
ON meters
FUNCTION(AVG(current))
INTERVAL(1h);
-- 查询命中:
SELECT _wstart, AVG(current) FROM meters
INTERVAL(1h); -- ✓ 命中
-- 查询不命中:
SELECT _wstart, tbname, AVG(current) FROM meters
PARTITION BY tbname INTERVAL(1h); -- ✗ 不命中(需按子表聚合)
-- 子表级 TSMA(需要更复杂的设计):
-- 通常用流计算更灵活
7. 管理 TSMA
sql
-- 查看所有 TSMA
SHOW TSMAS;
-- 查看特定库的 TSMA
SHOW TSMAS FROM db_name;
-- 查看详情
SELECT * FROM information_schema.ins_tsmas;
-- 删除
DROP TSMA tsma_name;
8. TSMA 性能与限制
开销:
① 写入开销:每个 TSMA 异步更新(< 5% 写入吞吐)
② 存储开销:每个 TSMA 占用空间(< 1% 原始)
③ 维护开销:失败时需要重算
限制:
① 仅支持基础聚合函数(不支持复杂窗口)
② TSMA 不支持 ORDER BY/LIMIT
③ 不支持包含 JOIN 的查询
④ TSMA 自身不可查询(只能通过原查询命中)
代码示例
真实场景:电力监控分层
sql
-- 原始秒级数据
CREATE STABLE meters (
ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT
) TAGS (location VARCHAR(32), groupid INT);
-- 5 分钟聚合(用于实时监控)
CREATE TSMA meters_5m ON meters
FUNCTION(AVG(current), MAX(current), MIN(current),
AVG(voltage), COUNT(*))
INTERVAL(5m);
-- 1 小时聚合(用于日报表)
CREATE TSMA meters_1h ON meters
FUNCTION(AVG(current), MAX(current), MIN(current),
AVG(voltage), MAX(voltage), MIN(voltage),
SUM(current * voltage), COUNT(*))
INTERVAL(1h);
-- 1 天聚合(用于年报)
CREATE TSMA meters_1d ON meters
FUNCTION(AVG(current), MAX(current), MIN(current),
AVG(voltage), MAX(voltage))
INTERVAL(1d);
查询自动加速
sql
-- 实时仪表盘(5 分钟粒度)
SELECT _wstart, AVG(current), MAX(current)
FROM meters
WHERE ts > now-1h
INTERVAL(5m);
-- → 命中 meters_5m,毫秒返回
-- 日报(小时粒度)
SELECT _wstart, AVG(current), AVG(voltage)
FROM meters
WHERE ts > now-7d
INTERVAL(1h);
-- → 命中 meters_1h,毫秒返回
-- 年报(日粒度)
SELECT _wstart, AVG(current), MAX(voltage)
FROM meters
WHERE ts > now-1y
INTERVAL(1d);
-- → 命中 meters_1d,秒级返回
性能考量
TSMA vs 直接查询
| 查询 | 无 TSMA | 有 TSMA |
|---|---|---|
| 1 小时聚合 1 月数据 | 30 秒 | 100ms |
| 1 天聚合 1 年数据 | 6 分钟 | 500ms |
| 5 分钟聚合 1 天 | 5 秒 | 50ms |
TSMA vs 流计算
| 维度 | TSMA | 流计算 |
|---|---|---|
| 创建复杂度 | 简单 | 中 |
| 灵活性 | 中 | 高 |
| 查询透明 | ✓ 自动 | 需查不同表 |
| 适用 | 标准聚合 | 复杂业务 |
FAQ
Q1: TSMA 和 RSMA 能共存吗?
可以。RSMA 在数据库级别配置,TSMA 在表级别。但不建议同时用(重复开销)。
Q2: 创建 TSMA 会重算历史吗?
会。新建 TSMA 后引擎会扫描历史数据回填。耗时取决于数据量。
Q3: 查询为什么没命中 TSMA?
常见原因:
- INTERVAL 不是 TSMA INTERVAL 整数倍
- 使用了 TSMA 未定义的函数
- WHERE 含数据列过滤
- PARTITION BY 与 TSMA 设计不符
Q4: TSMA 失败如何处理?
引擎自动降级到原始数据查询,结果正确但慢。后台会重试 TSMA 计算。
Q5: 修改 TSMA 函数?
不支持。需要 DROP 后重新 CREATE。
参考
系统构架篇
- 01-《TDengine 整体架构全景》
- 02-《集群拓扑深度解析》
- 03-《MNode 内部机制深度解析》
- 04-《RPC 通信层深度解析》
- 05-《VNode 生命周期》
- 06-《RAFT 共识协议》
- 07-《端到端的消息流》
数据模型
- 01-《数据库创建与参数详解》
- 02-《超级表/子表/普通表》
- 03-《支持数据类型深度解析》
- 04-《TDengine Tag 设计哲学与 Schema 变更机制》
- 05-《TDengine 虚拟表实现原理》
存储引擎
- 01-《TDengine 存储引擎概览》
- 02-《TDengine MemTable 深度解析》
- 03-《TDengine WAL 预写日志机制》
- 04-《TDengine 数据文件格式》
- 05-《TDengine Commit 与 Flush 机制 》
- 06-《TDengine Compaction 合并策略 》
- 07-《TDengine 数据保留与 TTL》
- 08-《TDengine 压缩编码机制》
- 09-《TDengine Cache 与 Last 查询加速》
- 10-《TDengine 逻辑计划生成》
查询引擎
- 01-《TDengine 查询引擎概览》
- 02-《TDengine SQL 解析与词法分析》
- 03-《TDengine 语义分析与 AST 重写》
- 04-《TDengine 逻辑计划生成》
- 05-《TDengine 物理计划生成》
- 06-《TDengine 扫描算子》
- 07-《TDengine 聚合算子》
- 08-《TDengine 聚合算子》
- 09-《TDengine 连接算子》
- 10-《TDengine 排序、填充与投影》
- 11-《TDengine 分布式查询执行》
- 12-《TDengine EXPLAIN 与查询优化》
数据写入
- 01-《TDengine SQL INSERT》
- 02-《TDengine 无模式写入》
- 03-《TDengine STMT 写入》
- 04-《TDengine 写入内部流程》
- 05-《TDengine 数据更新删除》
数据订阅
- 01-《TDengine 数据订阅》
- 02-《TDengine 订阅 vs Kafka》
- 03-《TDengine TMQ 消费流程》
- 04-《TDengine 内部机制》
- 05-《TDengine TMQ 最佳实践》
预聚合
关于 TDengine
TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。
