TDengine TSMA 窗口预聚集:按时间窗口预计算聚合结果的完整实践指南
发布时间:2026/9/13 23:06:48 作者:尧图编辑部 阅读量:1,286

TDengine TSMA 窗口预聚集按时间窗口预计算聚合结果的完整实践指南【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine本文围绕 TDengine 的 TSMATime-Range Small Materialized Aggregates时间范围小聚集机制展开覆盖 TSMA 的创建语法与命名/窗口约束、支持的聚合函数列表、Recursive TSMA 的构建方式、底层异步计算流程、querySmaOptimize/maxTsmaCalcDelay/tsmaDataDeleteMark等客户端参数的作用机制以及查询时 TSMA 自动选中的整除规则与各类回退场景。读完后你可以掌握如何为常用查询窗口设计并创建 TSMA、如何在查询中判断 TSMA 是否被命中、以及如何通过 Hint 或客户端参数强制回退到原始数据查询。1. 为什么需要 TSMA从块内 SMA 到时间窗口预聚集在大数据量场景下经常需要查询某段时间内的汇总结果。历史数据变多或时间范围变大时查询耗时也会随之增加。TDengine 的预聚集机制将计算结果提前存储后续查询直接读取聚集结果而不必扫描全部原始数据。当前数据块内的 SMASmall Materialized Aggregates信息即属此类。但块内 SMA 的粒度较小若查询时间范围为日、月甚至年涉及的数据块会很多逐块汇总仍然代价不菲。TSMA 正是为这类场景设计的它支持按用户指定的时间窗口做预聚集——对固定时间窗口内的数据预计算并落盘查询时优先使用预计算结果以提升性能。从源码结构看TSMA 在存储侧由 vnode 的 SMA 模块专门处理核心实现位于 smaTimeRange.c负责 TSMA 元数据创建、结果写入以及 TSMA 文件按天切分的计算逻辑例如根据interval与库的days配置推算每个 TSMA 文件覆盖的天数见该文件 L63-L108 的tdProcessTSmaGetDaysImpl管理侧则由 mnode 的 mndSma.c 处理创建/删除 TSMA 请求、SHOW TSMAS检索以及系统表数据维护。2. 创建 TSMA2.1 语法-- 创建基于超级表或普通表的 TSMA CREATE TSMA tsma_name ON [dbname.]table_name FUNCTION (func_name(func_param) [, ...] ) INTERVAL(time_duration); -- 创建基于小窗口 TSMA 的大窗口 TSMA CREATE RECURSIVE TSMA tsma_name ON [db_name.]tsma_name1 INTERVAL(time_duration); time_duration: number unit创建 TSMA 时需指定 TSMA 名称、表名、函数列表以及窗口大小。基于已有 TSMA 再创建时须使用RECURSIVE关键字且不能指定FUNCTION()新 TSMA 与所基于的 TSMA 拥有相同的函数列表。此时INTERVAL必须至少为所基于 TSMA 窗口长度的整数倍按天创建时不能基于2h或3h只能基于1h按月创建时只能基于1d而不能基于2d、3d。2.2 命名规则TSMA 命名规则与表名类似。名称最大长度受表名长度上限减去输出表后缀长度约束表名长度上限为193输出表后缀为_tsma_res_stb_对应源码常量TSMA_RES_STB_POSTFIX见 tcommon.h因此 TSMA 名称最大长度为178。TSMA 只能基于超级表和普通表创建不能基于子表创建。2.3 函数列表约束函数列表中只能指定下文支持的聚集函数且函数参数必须为 1 个即使该函数本身支持多参数参数必须为普通列名不能为标签列。函数列表中完全相同的函数与列会被去重例如同时创建两个AVG(c1)时只会保留一个输出。TSMA 计算会将所有函数中间结果输出到另一张超级表该表还包含原始表的全部标签列。函数个数上限为建表最大列数含标签列减去 TSMA 附加的四列_wstart、_wend、_wduration以及新增标签列tbname再减去原始表标签列数。超出限制时报Too many columns。由于输出为一张超级表行长度受最大行长度限制。不同函数的中间结果大小不一通常大于原始数据若输出行长度超限报Row length exceeds max length。此时需减少函数个数或将常用函数拆分到多个 TSMA。2.4 窗口范围与数量限制窗口大小范围为[1m, 1y/12n]。INTERVAL的单位与查询中INTERVAL子句相同参见 时间单位。TSMA 为库内对象但名称全局唯一。集群内可创建的 TSMA 个数受服务端参数maxTsmaNum限制默认值为10取值范围为[0, 10]。从源码看该参数在 tglobal.c 中注册作用域为CFG_SCOPE_SERVER服务端配置与文档描述一致。TSMA 后台计算使用流式计算每创建一条 TSMA 会对应创建一条流因此实际可创建数量还受已有流数量与最大可创建流数量限制。3. 支持的函数函数备注MINMAXSUMFIRSTLASTAVGCOUNT若需COUNT(*)应创建COUNT(ts)SPREADSTDDEV需要特别注意COUNT(*)的写法应创建COUNT(ts)来覆盖COUNT(*)查询。4. 删除 TSMADROP TSMA [db_name.]tsma_name;若存在基于当前 TSMA 创建的 Recursive TSMA删除会报Invalid drop base tsma, drop recursive tsma first。须先删除所有 Recursive TSMA。5. TSMA 的计算流式后台异步与最终一致性TSMA 的计算结果存放在与原始表同一数据库下的一张超级表中。该表对用户不可见、不可删除在DROP TSMA时自动删除。计算由流式计算在后台异步完成结果不保证实时性但保证最终正确性。几个值得注意的行为细节空子表不产出结果若原始子表内没有数据可能不会创建对应的输出子表因此在COUNT查询中即使配置了countAlwaysReturnValue也不会返回该表结果。历史数据回算窗口存在大量历史数据时创建 TSMA 后流式计算会先计算历史数据此期间新创建的 TSMA 不会被查询使用。增量重算数据更新、删除或过期数据到来时会自动重算受影响部分重算期间查询结果不保证实时性。强制回退若希望查询实时数据可在 SQL 中添加 Hint/* skip_tsma() */或将客户端参数querySmaOptimize设为0从原始数据查询。6. TSMA 的使用与客户端参数6.1 相关客户端配置参数querySmaOptimize是否在查询时使用 TSMA。1表示使用预计算结果0表示不使用、从原始数据查询默认值为0。该参数在 tglobal.c 中注册作用域为CFG_SCOPE_CLIENT客户端配置。maxTsmaCalcDelay单位为秒控制可接受的 TSMA 计算延迟。若 TSMA 计算进度与最新时间的差距在该范围内则使用该 TSMA超出则不使用。默认值60010 分钟最小值600最大值864001 天同样在 tglobal.c 中注册。tsmaDataDeleteMark单位为毫秒与流式计算参数deleteMark一致控制流式计算中间结果的保存时间。默认值1d86400000ms见 tglobal.c 中tsmaDataDeleteMark的初始值最小值1h。距最后一条数据的时间超过该配置的历史窗口不保存中间结果若修改这些窗口内的数据TSMA 结果可能不包含更新从而与查询原始数据不一致。6.2 查询时如何使用 TSMA已在 TSMA 中定义的聚合函数在多数查询场景下可直接使用。若存在多个可用 TSMA优先使用大窗口 TSMA未闭合窗口通过查询小窗口 TSMA 或原始数据计算。部分场景无法使用 TSMA见下文此时整条查询回退到原始数据计算。未指定窗口大小默认优先使用覆盖全部查询聚合函数、且窗口最大的 TSMA。例如SELECT COUNT(*) FROM stable GROUP BY tbname会使用包含COUNT(ts)且窗口最大的 TSMA。若聚合查询频率高应尽可能创建大窗口 TSMA。指定窗口大小带INTERVAL使用最大的可整除窗口 TSMA。窗口查询中INTERVAL的窗口大小、OFFSET以及SLIDING都会影响可用的 TSMA 窗口。可整除窗口 TSMA是指其窗口大小能被查询语句的INTERVAL、OFFSET、SLIDING整除的 TSMA。若窗口查询较多创建 TSMA 时需考虑常用窗口大小以及OFFSET、SLIDING。例如已创建窗口为5m与10m的两条 TSMA查询INTERVAL(30m)时优先使用10m查询INTERVAL(30m, 10m) SLIDING(5m)时仅可使用5m。6.3 查询限制在querySmaOptimize为1且未使用skip_tsma()Hint 时以下场景无法使用 TSMA某个 TSMA 中定义的聚合函数不能覆盖当前查询的函数列表。非INTERVAL的其他窗口或INTERVAL查询窗口大小含INTERVAL、SLIDING、OFFSET不是已定义窗口的整数倍。例如定义窗口为2m查询使用5m窗口时不可用但若还存在1m窗口则可以使用。查询WHERE条件中包含任意普通列非主键时间列的过滤。PARTITION BY或GROUP BY包含任意普通列或其表达式。可以使用其他更快的优化路径时例如 last cache 优化。若符合 last 优化条件优先走 last 优化无法走 last 时再判断是否可走 TSMA 优化。当前 TSMA 计算进度延迟大于配置参数maxTsmaCalcDelay。完整示例如下SELECT agg_func_list [, pseudo_col_list] FROM stable WHERE exprs [GROUP/PARTITION BY [tbname] [, tag_list]] [HAVING ...] [INTERVAL(time_duration, offset) SLIDING(duration)]...; -- 创建 CREATE TSMA tsma1 ON stable FUNCTION(COUNT(ts), SUM(c1), SUM(c3), MIN(c1), MIN(c3), AVG(c1)) INTERVAL(1m); -- 查询 SELECT COUNT(*), SUM(c1) SUM(c3) FROM stable; ---- use tsma1 SELECT COUNT(*), AVG(c1) FROM stable GROUP/PARTITION BY tbname, tag1, tag2; --- use tsma1 SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(1h); --- use tsma1 SELECT COUNT(*), MIN(c1), SPREAD(c1) FROM stable INTERVAL(1h); ----- cant use, spread func not defined, although SPREAD can be calculated by MIN and MAX which are defined. SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(30s); ----- cant use tsma1, time_duration not fit. Normally, query_time_duration should be multiple of create_duration. SELECT COUNT(*), MIN(c1) FROM stable WHERE c2 0; ---- cant use tsma1, cant do c2 filtering SELECT COUNT(*) FROM stable GROUP BY c2; ---- cant use any tsma SELECT MIN(c3), MIN(c2) FROM stable INTERVAL(1m); ---- cant use tsma1, c2 is not defined in tsma1. -- 基于 tsma1 再创建窗口为 1h 的 tsma2 CREATE RECURSIVE TSMA tsma2 ON tsma1 INTERVAL(1h); SELECT COUNT(*), SUM(c1) FROM stable; ---- use tsma2 SELECT COUNT(*), AVG(c1) FROM stable GROUP/PARTITION BY tbname, tag1, tag2; --- use tsma2 SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(2h); --- use tsma2 SELECT COUNT(*), MIN(c1) FROM stable WHERE ts 2023-01-01 10:10:10 INTERVAL(30m); -- use tsma1 SELECT COUNT(*), MIN(c1) MIN(c3) FROM stable INTERVAL(30m); --- use tsma1 SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(1h) SLIDING(30m); --- use tsma1 SELECT COUNT(*), MIN(c1), SPREAD(c1) FROM stable INTERVAL(1h); ----- cant use tsma1 or tsma2, spread func not defined SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(30s); ----- cant use tsma1 or tsma2, time_duration not fit. Normally, query_time_duration should be multiple of create_duration. SELECT COUNT(*), MIN(c1) FROM stable WHERE c2 0; ---- cant use tsma1 or tsma2, cant do c2 filtering从示例可以提炼出三条命中判定要点一是函数列表必须被 TSMA 的函数定义完整覆盖即使SPREAD可由MIN/MAX推算未显式定义即不可用二是窗口必须是 TSMA 窗口的整数倍且WHERE中只有时间列过滤才允许命中三是存在多条 TSMA 时优先选大窗口无INTERVAL查询选tsma2INTERVAL(30m)选tsma1而非tsma2。6.4 使用限制对原始表的影响创建 TSMA 之后对原始超级表有以下限制必须删除该表上的所有 TSMA 后才能删除该表。原始表的全部标签列不能删除也不能修改标签列名或子表的标签值须先删除 TSMA再删除标签列。若某些列被 TSMA 使用则这些列不能删除须先删除 TSMA。新增列不受影响但新增列不在任何已有 TSMA 中若要对新增列做预聚集需另行创建 TSMA。7. 查看 TSMASHOW [db_name.]TSMAS; SELECT * FROM information_schema.ins_tsma;其中ins_tsma系统表名与源码中的系统表定义对应见 systable.h 中TSDB_INS_TABLE_TSMAS的定义SHOW TSMAS的检索逻辑位于 mndSma.c 的mndRetrieveTSMA。若创建时指定的函数较多且列名较长显示函数列表时可能会被截断当前最大输出约 256KB。【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考