大范围聚合查询的成本
时序数据库的典型查询模式是在一个较大的时间范围上做聚合。例如统计某设备过去一年的日平均温度、某车间过去一个月的每小时最大功率、全线设备过去一周的日均值。这类查询的原始数据扫描量巨大——一年分钟级数据约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的流式计算与连续查询能力,将聚合计算下沉到存储引擎内部,是这一演进方向上较为完整的工程实践。

























