4. 数据存储与处理:时序数据库选型、清洗与压缩策略

大家好,我是老张。今天咱们聊聊综合能源系统里一个特别实在的话题——数据怎么存、怎么管。

你想想看,一个园区级的综合能源系统,光传感器就几百上千个。电表、气表、热表、光伏逆变器、储能BMS……每秒钟都在往外吐数据。这些数据要是存不好,后面做分析、做优化全是白搭。

我最早做项目时吃过这个亏。当时图省事,直接把数据往MySQL里塞。结果三个月后,单表数据量破亿,查询一条历史曲线要等十几秒。业主直接打电话骂人……嗯,从那以后我再也不敢轻视数据存储了。

4.1 时序数据库选型:InfluxDB vs TimescaleDB

先说结论:综合能源场景下,我个人更倾向用TimescaleDB。但这不是绝对的,得看你的具体需求。

为什么会有时序数据库这个东西?说白了,传统的关系型数据库是为“事务”设计的——你今天下了个订单,明天改了个地址,后天退了个货。但时序数据不一样,它只追加、不修改,而且天然带时间戳。用MySQL硬扛,就像用卡车运快递,能运,但效率低、成本高。

我整理了一个对比表,大家一看就明白:

特性 InfluxDB TimescaleDB
底层架构 自研TSM引擎 基于PostgreSQL
写入性能 极高(百万点/秒) 高(十万级/秒)
查询语法 类SQL(Flux/InfluxQL) 标准SQL
数据压缩比 10:1 ~ 30:1 5:1 ~ 15:1
与现有系统集成 需单独部署 可复用PG生态
适用场景 纯时序、高吞吐 时序+业务数据混合

我在项目中遇到过这样的情况:一个光伏电站监控系统,数据量不大但需要跟设备台账、运维工单做关联查询。用InfluxDB的话,得搞两套数据库,数据还得来回同步,麻烦得很。后来换成TimescaleDB,一张超表搞定所有,舒服多了。

但如果你做的是高频采集——比如电质量分析,采样率到kHz级别——那InfluxDB的写入性能确实更猛。这个得看你的实际场景。

我的选型建议:

  • 纯时序、高并发写入 → InfluxDB
  • 时序+业务数据混合、团队熟悉SQL → TimescaleDB
  • 已有PostgreSQL基础设施 → 无脑选TimescaleDB

4.2 数据清洗与插值:别让脏数据毁了你的模型

数据存进去了,但质量怎么样?我见过太多项目,数据是存了,但一查全是坑——传感器离线、通信丢包、数值跳变……用这种数据做优化,结果可想而知。

数据清洗,我一般分三步走:

  1. 去重:同一时间戳的多条记录,只保留一条
  2. 异常值剔除:超出合理范围的数据直接扔掉
  3. 缺失值插值:把空缺补上,保证时间序列连续

举个例子,光伏功率数据正常情况下应该在0到额定容量之间。如果某天突然蹦出来一个负值,或者一个比额定容量大10倍的值,那肯定是传感器抽风了。我一般用3σ原则或者箱线图法来识别这些异常点。

插值这块,我常用的方法有几种:

  • 线性插值:简单粗暴,适合变化平缓的数据(如温度)
  • 前向填充:用上一个有效值填充,适合开关状态类数据
  • 样条插值:曲线更平滑,适合功率、负荷这类波动数据

给大家看一段我常用的插值代码(Python + Pandas):

import pandas as pd
import numpy as np

# 假设df是原始数据,index是时间戳
df = df.resample('1min').mean()  # 重采样到1分钟粒度

# 线性插值
df['power_linear'] = df['power'].interpolate(method='linear')

# 前向填充(最多填充5个空值)
df['status_ffill'] = df['status'].fillna(method='ffill', limit=5)

# 样条插值(order=2表示二次样条)
df['power_spline'] = df['power'].interpolate(method='spline', order=2)

小技巧:插值不是万能的。如果连续缺失超过10个点,我建议直接标记为“无效时段”,而不是强行插值。否则会引入虚假数据,影响后续分析。

4.3 数据压缩与存储策略:省钱又省心

数据量大了,存储成本是个大问题。一个中等规模的园区,一年下来光原始数据就能攒几个TB。全存着?硬盘不要钱吗?

我一般用分层存储策略

  • 热数据(最近7天):原始精度,全量存储
  • 温数据(7天~3个月):降采样到1分钟粒度
  • 冷数据(3个月以上):降采样到15分钟或1小时粒度

这样做的好处很明显:查询近期数据时速度快,查询历史数据时虽然精度低一点,但做趋势分析完全够用。

压缩方面,TimescaleDB自带原生压缩功能,可以按列指定压缩算法。我一般这样配置:

-- 启用压缩
ALTER TABLE measurements SET (
  timescaledb.compress,
  timescaledb.compress_segmentby = 'device_id',
  timescaledb.compress_orderby = 'time DESC'
);

-- 创建压缩策略(每天压缩一次)
SELECT add_compression_policy('measurements', INTERVAL '7 days');

InfluxDB的压缩更激进,它默认就开启了。我实测过,同样的数据量,InfluxDB的磁盘占用只有TimescaleDB的60%左右。但代价是查询灵活性差一些——你没法做复杂的JOIN操作。

注意:压缩不是免费的午餐。压缩后的数据查询延迟会略有增加。如果你的系统对实时性要求极高(比如毫秒级响应),建议保留一部分数据不压缩,或者用缓存层来加速。

4.4 本章知识体系总览

下面这张图是我自己画的,把本章的核心逻辑串起来了。你看一眼就能明白数据从采集到存储的完整链路:

数据存储与处理核心流程 传感器数据采集 数据清洗 去重·异常剔除·插值 时序数据库选型 InfluxDB / TimescaleDB 存储策略 热数据·温数据·冷数据 数据压缩 原生压缩·降采样 关键原则:高频采集 + 智能清洗 + 分层存储 + 按需压缩 = 高效数据管理 综合能源系统数据量级:单站日均百万~千万条记录

这张图把整个流程串起来了:数据从传感器进来,先做清洗,然后根据场景选数据库,再按时间维度分层存储,最后用压缩技术省空间。每一步都环环相扣,缺一不可。

好了,关于数据存储与处理,我就讲这么多。记住一句话:存得好不好,直接决定你的平台能跑多远。别在这个环节省钱省力,不然后面有你哭的。


公众号:蓝海资料掘金营,微信deep3321