跳转至

16 时序数据与聚合

难度:中级|前置:数据库、MQTT|目标:从数据量和查询模式设计遥测存储

先算数据量

10 万设备,每 30 秒上报一次:

每秒约 3,333 条
每天约 2.88 亿条

如果每条原始记录加索引、元数据后占 300 字节:

每天约 86 GB

这只是粗估,但足以说明不能“先全存,之后再说”。

区分三类数据

数据 示例 特点
最新状态 当前温度、电量 高频读取,只需最新值
原始遥测 每次上报 写多、按时间查询
聚合数据 5 分钟均值、日最大值 用于趋势和报表

不要为了查当前值,每次扫描最新一条原始遥测。

表设计

时序表常见维度:

time
tenant_id
device_id
metric
value
quality

宽表还是窄表取决于指标稳定性和查询模式。没有一种模型适合所有设备类型。

时间分区

TimescaleDB Hypertable 按时间自动分为 chunk。查询带时间范围时只扫描相关 chunk。

仍然需要:

  • 合理 chunk 大小;
  • 常见查询索引;
  • 避免无时间范围的全表扫描;
  • 控制每条记录索引数量。

聚合和降采样

页面显示 30 天趋势不需要返回每 30 秒一个点。可以预计算:

  • 1 分钟;
  • 5 分钟;
  • 1 小时;
  • 1 天。

聚合保存 count、min、max、avg,而不只保存 avg,否则无法正确继续合并。

TimescaleDB Continuous Aggregate 可以增量维护聚合,降低反复扫描原始数据的成本。

保留策略

例如:

原始数据:30 天
5 分钟聚合:1 年
小时聚合:5 年

删除原始数据前,要确认所需聚合已经刷新完成。保留策略是产品和合规决策,不只是数据库配置。

乱序和设备时间

设备时钟可能不准。建议同时考虑:

  • device_time;
  • server_received_time;
  • 时钟质量;
  • 允许的迟到窗口;
  • 聚合如何修正迟到数据。

自测

  1. 为什么最新状态不应每次从原始遥测中查?
  2. 10 万设备 30 秒上报的日数据量如何估算?
  3. 为什么聚合最好保存 count、sum、min、max?
  4. 删除原始数据前要确认什么?

完成标准

  • 能估算消息条数和存储量
  • 能区分最新状态、原始和聚合数据
  • 能设计三层保留策略
  • 能解释设备时间与接收时间的差异

延伸阅读:Timescale HypertablesContinuous Aggregates

下一单元:规则、告警与去重