连续聚合与最新值缓存:时序数据库预聚合的性能工程实践

Xiaxin Li

2026-10-16 /

大范围聚合查询的成本

时序数据库的典型查询模式是在一个较大的时间范围上做聚合。例如统计某设备过去一年的日平均温度、某车间过去一个月的每小时最大功率、全线设备过去一周的日均值。这类查询的原始数据扫描量巨大——一年分钟级数据约50万点/设备,若设备数量上万,扫描量达数十亿点。

聚合查询的成本主要由数据扫描(I/O)与聚合计算(CPU)两部分构成。即便列式存储与向量化执行大幅降低了单位扫描成本,数十亿数据点的扫描仍耗时数十秒至数分钟。对于需要秒级响应的看板查询,直接扫描原始数据无法满足。

这是预聚合的动机。若在数据写入时或定期计算并存储聚合结果,查询时只需读取聚合结果,扫描量降低数个数量级。一年日聚合结果仅365点/设备,扫描量从50万点降至365点。用存储空间换取查询效率,是预聚合的核心取舍。

连续聚合与物化视图

连续聚合(Continuous Query,也常称为物化视图)是预聚合的实现机制。其语义是:定义一个聚合规则(源表、分组维度、时间窗口、聚合函数),系统持续或按需计算聚合结果并存储到目标表。

连续的语义包含两种实现方式。实时连续聚合在数据写入源表时同步更新聚合结果,查询聚合表即可获得最新数据,代价是写入路径增加了聚合计算开销。定时连续聚合按固定周期(如每分钟、每小时)批量计算增量窗口的聚合结果,写入开销低但有计算延迟。

时间窗口的滑动与对齐需要明确的语义。滚动窗口(Tumbling Window)将时间划分为不重叠的固定窗口,每个数据点归属唯一窗口。滑动窗口(Sliding Window)允许窗口重叠,同一数据点归属多个窗口,计算量随重叠度增加。会话窗口(Session Window)按数据活跃度动态划分。工业场景以滚动窗口为主,因为聚合结果的语义最清晰、存储最经济。

连续聚合的存储成本与查询收益需要权衡。每个聚合维度、每个聚合窗口都会生成一张聚合表,聚合表数量与维度组合数相关。若维度组合过多(每台设备、每个测点各一张),存储与管理开销上升。实践中按查询需求确定聚合粒度,避免为所有维度组合预计算。

聚合窗口

数据点/设备/年

适用查询

存储占用

原始(分钟)

52.5万

精确回溯

高

1分钟

52.5万

实时趋势

高

1小时

8760

日趋势/看板

低

1天

365

年报表

极低

1月

12

多年趋势

极低

降采样与多层次聚合

多层次聚合(Downsampling)是时序数据库为不同查询精度需求提供不同粒度聚合结果的机制。原始数据支撑精确回溯,小时级聚合支撑看板,天级聚合支撑报表,多级并存的架构兼顾精度与效率。

降采样的实现有两种路径。递进降采样(Cascading)从原始数据逐级计算——分钟聚合来自原始数据,小时聚合来自分钟聚合,天聚合来自小时聚合。这种方式计算量小(高层聚合不重复扫描原始数据),但误差会逐级累积(分钟均值再平均不等于原始数据的真均值)。独立降采样(Independent)各级聚合都从原始数据计算,精度高但计算量随级数增加。

均值、求和、计数类的聚合可以安全递进(前提是各级窗口是上一级的整数倍且样本数均匀);最大、最小、去重计数类聚合不能简单递进,需要保留中间状态(HyperLogLog、Min/Max Sketch等近似结构)。工业场景中,功率的日均值若用递进计算会产生偏差,更稳妥的做法是保留原始窗口的求和与计数,按需组合。

最新值缓存

现场看板与实时监控的核心需求是读取每个设备的最新值。若通过常规查询(按设备标签分组取最大时间戳的行),在设备数量大时查询开销明显。最新值缓存将每个设备时间线的最新值维护在一张内存表中,读取时直接命中。

最新值的实现方式有两种。独立的缓存表方案:写入时同步更新缓存表,读取时查询缓存表(读放大降低但写入路径增加维护成本)。内置函数方案:时序数据库提供的last_row / last 函数直接返回时间线的最新行,由存储引擎在读取路径优化,无需额外缓存表。

缓存与源数据的一致性需要保证。缓存表可能因写入失败、节点故障而与源表不一致。一致性策略上,强一致要求缓存与源表在同一事务或同一写入请求中更新;最终一致允许缓存滞后于源表,通过定时校正(定期从源表刷新缓存)保证最终收敛。工业监控场景通常接受秒级的一致性延迟,最终一致足够。

缓存策略

一致性

读延迟

写开销

适用场景

内置last_row

强

低

低

单设备最新值

独立缓存表

最终

极低

中

大屏批量读取

定时快照

最终(周期)

低

低

分钟级看板

实时计算

强

中

高

强一致需求

聚合粒度与刷新周期的选择

聚合粒度的选择依据查询精度需求与存储成本的权衡。经验法则是:保留原始数据用于精确回溯(或保留较短周期的原始数据),聚合数据长期保留用于趋势分析。原始数据保留90天、小时聚合约2年、天聚合长期保留,是较为常见的分层策略。

刷新周期的选择依据数据延迟容忍度。实时性要求高的看板需要分钟级甚至秒级刷新,实时连续聚合更适合;报表类查询容忍小时级延迟,定时连续聚合足够。刷新周期越短,写入路径的聚合开销越高。

聚合结果的重算与修正也是需要处理的问题。当源数据被修正(迟到数据写入、错误数据删除)时,已生成的聚合结果需要重算对应窗口。这要求聚合表记录其依赖的时间窗口,在源数据变更时触发相关窗口的重算。

结语

预聚合与缓存是时序数据查询性能优化的核心手段,其本质是用存储空间和写入开销换取查询效率。这一取舍没有固定答案——原始数据精度、聚合粒度、刷新周期、存储成本构成一个多维度的权衡空间,需要结合具体查询模式确定。从技术演进看,连续聚合正从”手动定义、定时计算”向”按查询模式自动推荐聚合策略”方向发展,让优化从依赖专家经验转向系统自动决策。TDengine的流式计算与连续查询能力,将聚合计算下沉到存储引擎内部,是这一演进方向上较为完整的工程实践。