去年 7 月份,我们接手了一个位于宁夏的 100MW 集中式电站。中午 12 点,发电功率达到峰值,每 5 秒一次的数据推送到后端的 InfluxDB 竟然出现了 10 秒以上的写入延迟。运维群里的报警信息炸了锅,前端看板上的功率曲线断断续续,活像心律不齐的心电图。
当时现场集成了 500 多台逆变器,加上汇流箱、环境监测仪和电表,总测点数超过了 5 万个。在那个项目之前,我们一直觉得 InfluxDB 是时序数据库(TSDB)的默认选项,毕竟它生态好、上手快。但那次「断流」事故让我们意识到,在大型光伏电站的监控架构里,数据库选型如果不结合具体的测点模型,最后大概率要交一笔昂贵的学费。
这篇文章想聊聊我们在架构选型时,针对 InfluxDB、TDengine 和 TimescaleDB 三款主流数据库做的深度实测与踩坑经历。不谈 PPT 上的性能指标,只说在 50 万甚至百万级测点并发下,一线工程师会面临的抉择。
InfluxDB 的「基数爆炸」梦魇
我们在早期架构中最常使用的是 InfluxDB 1.x 版本。它的 TSM 存储引擎在处理少量设备、高频采集时表现相当稳健。但光伏电站有一个典型的特征:标签(Tag)多,且具有层级结构(比如:省份-电站-阵列-设备SN)。
在宁夏那个项目中,为了方便查询,我们把逆变器的 SN、厂家型号、所属子阵列全部作为了 Tag。结果上线不到一周,内存占用直接飙升到 64GB 还没住。这就是典型的 Series Cardinality(系列基数)爆炸。InfluxDB 的索引是常驻内存的,当你的 Tag 组合(即 Series)达到数十万级别时,内存就会成为整个平台的瓶颈。
bash
# 这是一个典型的 InfluxDB 写入示例,看起来简单,但 Tag 滥用是噩梦的开始
curl -i -XPOST ' --data-binary 'inverter_power,sn=SN12345,site=ningxia,brand=huawei power=50.5 1625072400000000000'
更让人头疼的是删除操作。在光伏运维中,偶尔需要清理某个异常时间段的数据,InfluxDB 的删除是非常昂贵的。它不是物理删除,而是通过写入墓碑文件(Tombstones)来实现,这会导致查询性能在短时间内进一步恶化。如果你也打算用 InfluxDB 做 50MW 以上规模的电站,务必精简你的 Tag,把那些非必要的属性放进 Field 或者是关系型数据库里。
TDengine 的「一表一设备」真的香吗
在被 InfluxDB 的内存压力折磨后,我们开始测试国产的 TDengine。它的核心逻辑是「一个采集点一张表」,这对习惯了传统关系型数据库的工程师来说,初看觉得很怪异------如果有 1 万台逆变器,难道要在数据库里建 1 万张表吗?
实测证明,这种架构在处理大规模并发写入时确实有奇效。TDengine 将每个设备的数据在磁盘上连续存储,读取特定设备的功率曲线时,IO 效率极高。在华东某 50MW 分布式项目里,我们使用了 TDengine,5 万个测点的原始数据存储空间,竟然比 InfluxDB 节省了接近 80%。
sql
-- TDengine 的建表逻辑,超级表(STable)是核心
CREATE STABLE inverter (ts timestamp, power float, voltage float)
TAGS (sn binary(20), site_id int);
-- 为具体设备自动建表
CREATE TABLE inv_001 USING inverter TAGS ('SN_ZH_001', 101);
但 TDengine 也不是通用的。它的 SQL 支持虽然号称高度兼容,但在处理复杂的跨表关联(Join)时,依然不如 Postgres 体系。另外,它的集群版在早期版本中配置较为繁琐,对于那些只需要简单单机部署的小型 EPC 平台来说,运维成本反而略高。我们团队内部的共识是:如果你追求出色的存储性能和写入吞吐,且数据模型相对固定,TDengine 是目前头部的选择。
TimescaleDB:给 SQL 老兵的后悔药
最后说说 TimescaleDB。它本质上是 PostgreSQL 的一个插件,通过「超表」(Hypertables)把大表自动切分成一个个按时间排序的 Chunk。
我们之所以在某些项目中依然坚持使用 TimescaleDB,是因为它对 SQL 的支持是完全体。在光伏监控平台里,我们不仅要存时序数据,还要存大量的元数据:电站合同信息、发电设备台账、消纳比例计算等。如果你用 TimescaleDB,你可以直接在一个 Query 里把实时功率和电站的合同单价做 Join,算出这一小时赚了多少钱。这在 InfluxDB 里几乎是不可能完成的任务。
sql
-- TimescaleDB 示例:直接进行关联查询,业务开发最爱
SELECT time_bucket('1 hour', ts) AS hour,
SUM(power * price) AS revenue
FROM power_data p
JOIN site_contracts c ON p.site_id = c.site_id
GROUP BY hour;
当然,代价也是显而易见的。在同等配置下,TimescaleDB 的写入吞吐量大约只有 TDengine 的三分之一,存储压缩率也逊色不少。它更适合那些对业务逻辑要求复杂、数据量在千万级以下、且团队对 PostgreSQL 极度熟悉的场景。
实测数据对比:性能、成本与运维
为了给选型提供依据,我们在实验室环境下模拟了 500 个设备、每秒 1 次采集、持续 24 小时的压力测试。以下是我们内部记录的参考数据:
| 指标 | InfluxDB 1.8 | TDengine 3.0 | TimescaleDB |
|---|---|---|---|
| 写入吞吐(测点/秒) | 约 15 万 | 约 80 万 | 约 10 万 |
| 磁盘占用 (1 亿条数据) | 约 4.2 GB | 约 0.8 GB | 约 12.5 GB |
| 查询延迟 (1k 测点聚合) | 280ms | 45ms | 310ms |
| 内存消耗 | 高(随基数增长) | 低(稳定) | 中(PG 缓存机制) |
| 学习曲线 | 低 | 中 | 极低(只要会 SQL) |
在构建我们内部的 ZenovaConnect 聚合层时,我们也曾在这个十字路口犹豫了很久。最终我们采取了分层策略:在边缘侧(Edge)由于资源受限,优先采用轻量化的存储方案;在云端中台,针对不同的客户体量,提供 TDengine 和 TimescaleDB 的适配驱动。
我们的取舍逻辑
选型没有标准答案,只有「此时此刻」的最优解。如果你的项目属于以下三类场景,可以参考我们的建议:
- 纯粹的监控看板,数据量极大:选 TDengine。它能帮你省下大笔的云服务器磁盘费用,且在高并发写入下最稳。
- 业务逻辑复杂,需要频繁关联业务表:选 TimescaleDB。别低估了 SQL 的生命力,它能让你的后端开发少写 50% 的脏代码。
- 存量项目升级,且已有现成的 InfluxDB 经验:可以继续用,但切记要控制 Tag 的基数,并配置好数据保留策略(Retention Policy)。
很多时候,架构的崩溃不是因为数据库不行,而是因为我们对数据模型缺乏敬畏。在光伏这种长周期、高频率的工业场景下,每一条没用的 Tag 都是未来埋下的雷。你目前在用的时序数据库,在高并发下出现过哪些让你意想不到的坑?欢迎在评论区一起交流。
了解 ZenovaConnect 完整方案