一家中型制造企业上线了设备监控系统,300 台设备 × 每秒 5 条采样数据 = 每天 1.3 亿条记录。上线第一周,MySQL 的慢查询把运维钉钉打爆了。时序数据不是关系型数据——这句教训由一张张阿里云账单写成的,代价不低。
"工业物联网场景下,时序数据库到底怎么选?" 这是近两年技术社区里反复出现的问题。TDengine、InfluxDB、TimescaleDB —— 三个名字频上热榜,但各自的设计哲学和适用边界差异巨大。本文基于公开 benchmark 数据和实际项目经验,做一次系统性的技术评测。
▲ 三大时序数据库综合评分对比(来源:腾讯云开发者社区)
1. 先搞清楚三个概念
在进入对比之前,快速厘清几个核心概念——它们决定了时序数据库的设计取舍。
时序数据(Time-Series Data) :按时间顺序排列的数据点序列,每个点由 (timestamp, metric, tags) 组成。工业场景典型特征:写入远大于读取、数据只追加不修改、查询多为聚合操作。
列式存储 vs 行式存储:时序数据库普遍采用列式存储,因为聚合查询(如 AVG(temperature) WHERE device_id='sensor_1' AND time > now()-1h)只需要扫描目标列,IO 效率比传统行式存储高出几个数量级。
降采样(Downsampling) :工业数据原始精度可能是毫秒级,但看历史趋势只需要分钟级甚至小时级粒度。降采样策略直接影响存储成本——这是选型时最容易忽略的隐性指标。
▲ 工业数据从采集到前端展示的标准链路
2. 三个选手的技术画像
TDengine
涛思数据出品,国内开源时序数据库的头部项目。核心架构是"一个数据库搞定消息队列+存储+计算"——内置 MQTT 接入、流式计算引擎和缓存层,不需要额外搭 Kafka。
技术栈:C 语言编写,自研存储引擎,原生分布式架构。支持标准 SQL,提供 RESTful API。
设计哲学:"超级表"模型——一个超级表对应一类设备,子表对应具体设备实例。这种设计天然匹配工业 IoT 的设备层级结构,查询时不需要 JOIN。
InfluxDB
老牌时序数据库,由 InfluxData 公司维护。目前主推 InfluxDB 3.0(云原生架构),但社区仍大量使用 1.x 和 2.x 版本。
技术栈:Rust 重写的 3.0 版本,底层采用 Apache Arrow 列式格式。查询语言从 InfluxQL 演进到 Flux,3.0 又回归 SQL。
设计哲学:Measurement + Tag + Field + Timestamp 的四元数据模型。生态成熟度最高——Grafana 原生支持、Telegraf 数据采集、Kapacitor 告警,一站式 TICK Stack。
TimescaleDB
PostgreSQL 的时序扩展插件。对于已深度使用 PostgreSQL 的团队,TimescaleDB 是"零迁移成本"的选择。
技术栈:C 语言编写,以 PostgreSQL 扩展形式运行。Hypertable(超表)自动分区,支持标准 SQL 和 PostgreSQL 全部生态。
设计哲学:不做专用时序数据库,而是把 PostgreSQL 变成一个能打的时序数据库。优势是完整的 SQL 支持、JOIN 能力强、生态兼容——代价是极致性能不如专用引擎。
▲ InfluxDB 的技术架构全景(来源:CSDN)
3. 多维对比
3.1 写入性能
这是工业场景最关键的指标——设备数据是持续写入的,写慢了直接丢数据。
| 指标 | TDengine | InfluxDB | TimescaleDB |
|---|---|---|---|
| 单机写入吞吐 | 🟢 极高(100万+ points/s) | 🟡 高(25万+ points/s) | 🟡 中高(20万+ points/s) |
| 10,000 设备并发写入 | 🟢 线性扩展 | 🟡 随设备数下降明显 | 🟡 依赖 PG 配置调优 |
| 写入资源开销 | 🟢 CPU 低,内存占用小 | 🟡 适中 | 🔴 偏高(PG 基础开销) |
| 数据压缩比 | 🟢 10-20x | 🟡 5-10x | 🟡 3-8x |
TSBS(Time Series Benchmark Suite)公开测试数据显示:在全部 cpu-only 五个场景中,TDengine 写入性能相对于 InfluxDB 最领先的场景是其 10.6 倍,最小差距也达到 3.0 倍。
▲ TDengine vs TimescaleDB vs InfluxDB 写入速度对比(来源:博客园)
3.2 查询性能
| 查询类型 | TDengine | InfluxDB | TimescaleDB |
|---|---|---|---|
| 最新数据点查询 | 🟢 读缓存,毫秒级 | 🟡 需扫描存储引擎 | 🟡 依赖 PG 缓存策略 |
| 简单聚合(1h 窗口) | 🟢 极快 | 🟡 中速 | 🟢 快(PG 查询优化器) |
| 复杂双滚动聚合 | 🟢 领先 24-26x | 🔴 较慢 | 🔴 较慢 |
| 跨设备联合查询 | 🟡 需超级表设计 | 🔴 不适合 JOIN | 🟢 原生 SQL JOIN |
在 stationary-trucks 查询场景中,TDengine 的查询性能是 InfluxDB 的 132 倍,是 TimescaleDB 的 8 倍。TimescaleDB 在复杂 JOIN 查询上凭借 PostgreSQL 成熟优化器有一定优势。
3.3 运维与生态
| 维度 | TDengine | InfluxDB | TimescaleDB |
|---|---|---|---|
| 部署复杂度 | 🟢 极简(单二进制) | 🟡 中等 | 🔴 依赖 PG 运维经验 |
| 集群方案 | 🟢 原生分布式 | 🟢 3.0 云原生 | 🟡 需要 PG 集群方案 |
| Grafana 集成 | 🟢 官方数据源 | 🟢 原生支持 | 🟢 通过 PG 数据源 |
| 中文社区 | 🟢 极其活跃 | 🟡 有中文资料 | 🔴 较少 |
| 商业支持 | 🟢 涛思数据企业版 | 🟢 InfluxDB Cloud | 🟢 Timescale Cloud |
| SQL 兼容性 | 🟡 标准 SQL 子集 | 🟡 Flux/InfluxQL/SQL 混用 | 🟢 完整 PostgreSQL SQL |
4. 前端集成实战
选型不是自嗨,最终数据要推到大屏上看。下面是三个数据库在 Node.js 后端集成中的典型代码片段。
4.1 TDengine 集成
// 使用 @tdengine/rest 连接器
const { options, connect } = require('@tdengine/rest');
const conn = connect({
host: 'localhost',
port: 6041,
user: 'root',
pass: 'taosdata',
});
// 查询最近 1 小时温度平均值
async function getAvgTemperature(deviceId) {
const query = `
SELECT AVG(temperature)
FROM devices.d001
WHERE ts > NOW - 1h
INTERVAL(1m)
`;
const result = await conn.query(query);
// result 直接返回行数据数组,无需额外解析
return result.getData();
}
优势:RESTful 接口原生支持 JSON 返回,前端调试方便;超级表设计使得按设备查询无需拼接 SQL。
4.2 InfluxDB 集成
// 使用 @influxdata/influxdb-client
const { InfluxDB, Point } = require('@influxdata/influxdb-client');
const client = new InfluxDB({
url: 'http://localhost:8086',
token: 'my-token',
});
const queryApi = client.getQueryApi('my-org');
// Flux 查询语言——语法差异较大
async function getAvgTemperature(deviceId) {
const fluxQuery = `
from(bucket: "industrial")
|> range(start: -1h)
|> filter(fn: (r) => r["_measurement"] == "temperature")
|> filter(fn: (r) => r["device_id"] == "${deviceId}")
|> aggregateWindow(every: 1m, fn: mean)
`;
const result = [];
return new Promise((resolve, reject) => {
queryApi.queryRows(fluxQuery, {
next(row, tableMeta) {
result.push(tableMeta.toObject(row));
},
error: reject,
complete: () => resolve(result),
});
});
}
注意:Flux 语法与 SQL 差异明显,团队学习成本偏高。InfluxDB 3.0 已支持 SQL 查询,但 2.x 版本仍需 Flux。
4.3 TimescaleDB 集成
// 使用 pg 驱动——标准 PostgreSQL 连接
const { Pool } = require('pg');
const pool = new Pool({
host: 'localhost',
port: 5432,
database: 'industrial',
user: 'postgres',
password: 'password',
});
async function getAvgTemperature(deviceId) {
const query = `
SELECT
time_bucket('1 minute', time) AS bucket,
AVG(temperature) AS avg_temp
FROM sensor_data
WHERE device_id = $1
AND time > NOW() - INTERVAL '1 hour'
GROUP BY bucket
ORDER BY bucket
`;
const result = await pool.query(query, [deviceId]);
return result.rows;
}
优势:标准 SQL + 参数化查询,安全且团队上手成本最低。time_bucket() 是 TimescaleDB 提供的核心函数,自然直观。
4.4 WebSocket 实时数据推送
无论选哪个数据库,前端实时展示的最后一公里都一样——通过 WebSocket 推送:
// Node.js WebSocket 服务端
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
// 每 5 秒查询一次 TDengine 最新数据并推送
setInterval(async () => {
const latestData = await conn.query(
'SELECT LAST(*) FROM devices.d001'
);
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'realtime',
data: latestData.getData(),
timestamp: Date.now(),
}));
}
});
}, 5000);
// 前端接收
const ws = new WebSocket('ws://localhost:8080');
ws.onmessage = (event) => {
const { data } = JSON.parse(event.data);
// 更新组态画面 / ECharts 图表
updateDashBoard(data);
};
▲ InfluxDB vs TDengine 查询响应时间对比(来源:TDengine 官方)
5. 选型建议——分场景说清楚
没有最好的数据库,只有最合适的数据库。 以下是基于公开 benchmark 和实践经验的选型矩阵:
▲ 时序数据库选型决策树
| 场景 | 推荐方案 | 核心理由 |
|---|---|---|
| 大型工厂(5000+ 设备,高频采集) | TDengine | 写入吞吐最高,超级表模型天然匹配设备层级,内置流计算免去 Kafka |
| 已有 PG 体系的中型项目 | TimescaleDB | 零迁移成本,SQL 完善,JOIN 方便,运维团队无需学新技术 |
| 海外部署 / Grafana 重度用户 | InfluxDB 3.0 | TICK Stack 生态闭环,云服务成熟,英文文档完善 |
| 国产化 / 信创要求 | TDengine | 国产开源、中文社区活跃、企业版有商业支持 |
| 混合负载(时序 + 业务数据) | TimescaleDB | PostgreSQL 原生支持 JSONB、全文搜索、地理空间,一库多用 |
特别提醒几个容易踩的坑:
- 不要用 MySQL/MongoDB 硬扛时序数据——写入性能会随数据量指数衰减,这是由存储引擎设计决定的,不是加索引能解决的
- InfluxDB 2.x → 3.0 的迁移路径不平滑——Flux 查询到 SQL 的切换、数据格式变化都需要重新适配
- 降采样策略要在上线前设计好——一旦数据量起来再改,历史数据迁移的成本按 TB 计算
6. 总结
时序数据库选型没有标准答案,但有清晰的决策路径:
- 追求写入性能极致 + 国内生态→ TDengine
- PG 技术栈复用 + 复杂查询→ TimescaleDB
- 国际化 + 监控告警闭环→ InfluxDB
在工业物联网场景下,数据写入是生产环节、查询是消费环节,存储成本是持续成本。选型时算一笔账:3 年存储成本 + 2 人运维成本 + 团队学习成本,往往比 benchmark 上那几个百分点的性能差距更有决策价值。
上代码验证,跑个分看数据——这是技术人的基本素养。但最终决策,还得回到业务场景。