⚖️ 丁丁选型对比系列 · 第5篇

工业历史数据用什么存?
MySQL vs TDengine / InfluxDB

💡 MySQL 到底能不能存工业历史数据?多少点位、多大数据量就该上时序库?这篇一次算清楚。

这是比"哪个时序库更好"更前置的一个决策:你到底要不要上时序库。很多团队图熟悉,用 MySQL 建张点位表存历史,几个月后查询变慢、磁盘暴涨。这篇给你一张按测点规模算数据量的决策表,再用 10 个维度说清关系库和时序库的边界,以及已经用了 MySQL 该怎么平滑迁移。

对比对象MySQL + 2 款时序库
对比维度10 项
决策依据按规模算数据量
一句话关系库存业务,时序库存历史
🎯 丁丁一句话结论

不是二选一,而是各管一摊:MySQL 存会增删改、要关联的业务数据(用户、工单、配方、报警主数据、台账);时序库存只追加、按时间查的点位历史。判断点位历史要不要上时序库,就看你的写入量——几十点、5 秒以上、只看近期,MySQL/SQLite 够用;点上百、秒级写、要存多年趋势,直接上时序库,工业现场选 TDengine,IT 监控选 InfluxDB。

01 先算一笔账:你的数据一年多少行、占多少磁盘

选型争论之前,先把自己的数据量算出来,这是最客观的依据(假设每个点位每次采样落一行):

每秒写入行数 = 点位数 ÷ 采样周期(秒)
每天行数 = 每秒行数 × 86400
每年行数 = 每天行数 × 365

举个最常见的产线例子:500 个点、每 2 秒采一条 = 250 行/秒,一天 2160 万行,一年约 78.8 亿行。按行存约 50 字节/行(含主键、设备、点位、时间、值和索引)估算,一年约 394 GB;时序库列存压缩后通常只有 约 1/10(40 GB 上下)。这还没算查询变慢和备份成本。

规模 测点 采样周期 写入 年数据量 磁盘(估算) 建议
单机 / 小设备 ≤ 50 点 5 ~ 10 秒 5 ~ 10 行/秒 约 1.6 ~ 3.2 亿行 约 8 ~ 16 GB / 年 SQLite / MySQL 够用
单产线 / 小车间 100 ~ 500 点 2 ~ 5 秒 50 ~ 250 行/秒 约 16 ~ 79 亿行 关系库约 80 ~ 400 GB,时序库约 1/10 上时序库
多机 / 整车间 1000 ~ 5000 点 1 秒 1000 ~ 5000 行/秒 约 315 ~ 1577 亿行 关系库约 1.5 ~ 7.7 TB,时序库约 1/10 必须时序库 + 容量规划
多车间 / 全厂 万点以上 秒级 1 万+ 行/秒 千亿级 / 年 数十 TB 级 分布式集群,先做架构设计
📌 三个经验阈值(出现任一条,就别再用 MySQL 硬扛点位历史):
  • 预计单表 超过 1000 万行,开始评估时序库;
  • 单表 上亿、查一条曲线要几秒、磁盘每月涨几十 GB,立刻上;
  • 即使量不算大,但要存多年趋势、做降采样聚合、多机联网看板,也建议直接上时序库。

注:磁盘按每行约 50 字节、时序库列存压缩约 1/10 的工程量级估算,实际与数据类型、压缩算法、是否含索引强相关,正式选型请以实测为准。

02 为什么 MySQL 扛不住高频点位

不是 MySQL 不好,而是负载不对口。工业点位数据有鲜明特点:只追加、几乎不修改、带时间戳、按时间范围查、数据结构高度同质、要长期保留。这恰好是通用 OLTP 关系库最不擅长的活:

  • 写入:B+ 树索引在持续高频插入下要不断分裂、刷盘,写得越久越慢,还得靠批量插、关索引、分表来扛。
  • 查询:看板几乎都是"查某设备最近 1 小时趋势""昨天某班曲线",关系库靠索引扫,单表上亿后一次查询几秒到几十秒。
  • 压缩:行存对大量重复结构的数值压缩率极低,磁盘占用是时序库的约 10 倍。
  • 生命周期:没有内置时间窗口聚合、降采样、自动过期,全要自己写定时任务和 DELETE,删海量历史数据本身就是灾难。

时序数据库就是针对"高写入、按时间查、自动压缩、自动过期"这四件事重新设计的——按时间顺序追加写、列存高压缩、时间分区让范围查询毫秒级、原生降采样和保留策略。

03 10 个维度逐项对比:MySQL / TDengine / InfluxDB

对比维度 MySQL(关系库) TDengine(工业时序) InfluxDB(通用时序)
设计定位 通用 OLTP 关系库,为事务、关联和增删改查设计 工业物联网专用时序库,为高频写入和按时间查设计 通用时序库,最初为 IT/DevOps 监控指标设计
存储模型 行存 + B+ 树索引,一行一个点一条记录 列存 + 一设备一子表/超级表,同构数据压缩 列存 + measurement/tag 模型,同类指标压缩
写入吞吐 每秒几百到几千行就开始吃力,再高要分表、批量插、关索引 单机 10 万+ 行/秒,顺序追加写,不维护 B+ 树 单机数万行/秒,批量写入优化好
磁盘占用 行存几乎不压缩,按约 50 字节/行(含索引)估算 列式压缩,同类型浮点常压到 1/10 甚至更低 列式压缩,约 1/10,高压缩比
按时间查曲线 靠时间索引,数据上亿后一次曲线查询要几秒到几十秒 按时间分区,查一条曲线毫秒级 按时间分片,时间范围查询毫秒级
降采样 / 聚合 没有原生时间窗口,要自己写定时任务、物化视图,越跑越重 原生 INTERVAL 时间窗口、连续查询、自动降采样 连续查询 / Flux 任务,原生按时间聚合
数据保留 没有过期策略,要自己写 DELETE 或分区,删海量数据很痛苦 KEEP 参数自动过期、按天归档,无需手工删 retention policy 自动过期,按库配置
按设备组织 靠设备表、点位表外键关联,查询带 JOIN 一个设备一张子表,查设备天然带索引 用 tag 区分设备、点位,无 JOIN
事务 / 关系查询 强,ACID、JOIN、唯一约束,这是它的主场 弱,不擅长多表关联和事务(也不该用它干这个) 弱,无传统关系概念
典型用途 用户、权限、工单、配方、报警主数据、配置、业务台账 工业现场海量测点历史、采集存储一体、国产替代 IT/DevOps 监控指标、服务器/应用监控,配 Telegraf+Grafana
📌 关键认知:这不是"谁取代谁",而是"分工"。

一个成熟的工控系统,业务数据(用户、权限、工单、配方、报警主数据、台账)放 MySQL,点位历史放 TDengine 或 InfluxDB,可视化用 Grafana。强行用 MySQL 存时序数据,或者反过来用时序库存业务数据,都是拿工具的短板去硬扛。

04 对号入座:你该怎么选

🗃️
继续用 MySQL / SQLite,如果你:
  • 测点几十以内、采样 5 秒以上
  • 单机上位机,只看近期数据、存几个月
  • 主要是配置、工单、报警等业务数据
  • 团队只有关系库,没有专职运维
  • 愿意用索引、归档、分表把规模控制住
🏭
上 TDengine,如果你:
  • 工业现场高频写入,测点成百上千
  • 要内置 MQTT/OPC UA/Modbus,采集存储一体
  • 做国产替代 / 信创,要中文社区和工业案例
  • 要高压缩、降采样、自动过期,存多年历史
  • 注意开源版 AGPL,闭源商用要评估授权
🖥️
选 InfluxDB,如果你:
  • 做 IT/DevOps 服务器、应用监控指标
  • 用 Telegraf + InfluxDB + Grafana 经典组合
  • 团队是 Go 栈,要最宽松 MIT 协议
  • 规模中等、监控对象偏软件而非 PLC
  • 要最多教程和最成熟的国际生态

05 已经用了 MySQL?不用推翻,这样平滑迁移

很多项目是"先用 MySQL 跑起来,量大了再优化",这很正常。我的建议是旁路并行、逐步切换,而不是停机重构:

  1. 新数据先旁路:新增的点位数据通过 Telegraf / Neuron / ThingsGateway 等采集器,一路写 MySQL(保留)、一路写时序库(新增),业务系统不动。
  2. 业务数据留 MySQL:用户、工单、配方、报警主数据、设备台账继续用关系库,不要迁。
  3. 历史数据分批导:按时间把旧数据导出成 CSV,批量导入 TDengine,导完一批核对一批,避开停机窗口。
  4. 应用层统一接口:趋势/曲线查询读时序库,业务查询读 MySQL,上层通过统一数据访问接口屏蔽底层,以后换库也不影响应用——这也是我在通讯库里一直强调的"应用与存储解耦"。

迁移前,还可以先在采集侧做死区上报、分级采样、降采样,把不必要的写入量先降下来(见 FAQ 最后一条),很多项目这样优化后规模本身就小了一大截。

06 丁丁的实战建议

我在冲床监控、能源管理、OEE 这些项目里,点位历史基本都用 TDengine,业务数据放 MySQL/PostgreSQL,看板用 Grafana——这套分工让我在 30 台冲床、几千点的规模下,采集存储基本不用操心磁盘和查询。

但我也经常帮小项目主动克制:一个单机检测设备、几十点、数据就给操作工看几天,我会直接用 SQLite,绝不为了"技术先进"硬塞时序库。选型的核心不是追新,而是先算清自己的数据量和使用场景。

真正要避免两种极端:一是该上不上,让 MySQL 硬扛几十亿行,最后查询超时、磁盘爆满;二是不该上乱上,几十点的小项目也搞一套时序库集群,增加运维负担。按上面那张规模表对号入座,基本不会错。

常见问题 FAQ(选型时最常被问)

Q:MySQL 到底能不能存工业历史数据?

A:能,但有明确边界。点位少(几十点以内)、采样周期 5 秒以上、主要看最近几天数据、对历史趋势和降采样没要求,MySQL 甚至 SQLite 都能稳定跑。一旦测点上百、秒级写入、要存几年历史、要画趋势曲线和做小时/班次级聚合,关系库就会越用越慢、磁盘暴涨,这种负载应该交给时序数据库。

Q:多少点位、多大数据量就该上时序数据库?

A:自己算一笔账:每秒写入行数 = 点位数 ÷ 采样周期(秒),年行数 = 行/秒 × 86400 × 365。经验阈值:预计单表超过 1000 万行就要开始评估;单表上亿、或查一条曲线要几秒、磁盘每月涨几十 GB,就该立刻上时序库。举例:500 点每 2 秒一条,一年约 78.8 亿行、按行存约 394GB,时序库压缩后约 40GB 且查询毫秒级——这个量级已经没有理由再用 MySQL 硬扛。

Q:我用 MySQL 分区表、分库分表,能替代时序库吗?

A:能缓解,但治标不治本。分区表和分表能把单表变小、让查询少扫一些数据,但仍然缺三样时序库原生的东西:高压缩比(磁盘还是大)、自动时间窗口降采样、自动过期策略。你需要自己维护分区、写聚合任务、写清理脚本,本质是在关系库里手工重造时序库的轮子,而且持续高频写入下 B+ 树索引的维护成本依然在。数据量大了,这套手工方案的维护成本会超过上一个时序库。

Q:上了时序库,原来的 MySQL 是不是要废弃?

A:不是,正确做法是两者配合、各管一摊。MySQL 继续存它擅长的:用户、权限、工单、配方、设备台账、报警主数据等"会增删改、要关联"的业务数据;时序库专存"只追加、按时间查"的点位历史。绝大多数工控系统最终都是 MySQL + 时序库并存,而不是二选一。

Q:单机上位机用 SQLite 存历史数据够用吗?

A:够,而且是合理选择。单机上位机、点位几十、秒级、只存几个月到一两年,SQLite 零部署、免维护、单文件备份,比上时序库更省心。但要注意:合理建索引、控制单表规模、定期归档(比如把一年前的数据转到历史表)。一旦点位涨到几百、或要做看板/多机联网,再升级到时序库,SQLite 就留在本地做缓存和短期缓存。

Q:现在 MySQL 里已经堆了很多历史数据,怎么迁到 TDengine?

A:不要一次性推翻,分四步:①新数据先双写或用 Telegraf 等采集器旁路写时序库,业务不动;②MySQL 继续存业务数据和近期数据;③历史数据按时间分批导出(CSV)再导入 TDengine,导完一批验一批,避免停机迁移;④应用层走统一的数据访问接口,趋势查询读时序库、业务查询读 MySQL。这样切换平滑、风险小,也符合"应用与存储解耦"的架构。

Q:时序数据库能存工单、报警配置、用户权限吗?

A:不建议。这些是会频繁更新、要事务保证、要关联查询的业务数据,是关系库的主场,应该留在 MySQL/SQLite。时序库存的是"发生了什么"(测点随时间的值),关系库存的是"谁、配置、规则、记录",两者不要混用。报警历史这种带时间的流水可以进时序库,但报警规则、确认人、处理工单这类主数据放关系库。

Q:暂时不想上时序库,采集侧能不能先把数据量降下来?

A:能,而且应该先做。三招立竿见影:①死区/变化上报——值变化超过阈值才存,平稳的温度压力不用每秒落库;②分级采样——关键点位秒级、普通点位 5~10 秒、趋势点位分钟级;③降采样——原始数据存短期,自动聚合成分钟/小时值长期保留。很多项目优化完数据量能降一个数量级,MySQL 又能扛很久;但注意别为了省存储把事故追溯需要的原始数据丢了。

拿不准你的项目该用 MySQL 还是时序库?

把你的点位数、采样周期、要存多久、现在用什么库告诉我,丁丁帮你算清数据量、定一套不浪费服务器、也不返工的存储方案,并给出迁移路径。

联系丁丁选型咨询 →

三款时序库怎么选(TDengine/InfluxDB/IoTDB)→ 返回全部评测