物联网设备每秒上报温度、服务器每分钟采集 CPU 指标、GPS 每 100ms 记录一次坐标------这类数据有一个共同特征:带时间戳、持续产生、按时间查询。
把这类数据塞进 MySQL 当然能存,但随着数据量增大,查询会越来越慢,存储也会越来越臃肿。时序数据库(Time Series Database,TSDB)正是为解决这个问题而生的。
一、什么是时序数据?
时序数据(Time Series Data)就是按时间顺序排列的一系列数据点,每条记录都包含:
- 时间戳:数据产生的时刻
- 度量值:实际的数值(温度、速度、CPU 使用率等)
- 标签/标识:数据来自哪个设备、哪个传感器
举个例子,一个气象站每分钟上报一次数据:
时间戳 站点ID 温度 湿度 气压
2024-01-01 08:00 station_A 12.3 65% 1013
2024-01-01 08:01 station_A 12.4 64% 1013
2024-01-01 08:02 station_A 12.2 66% 1012
这类数据有几个特点:
- 写多读少:持续高频写入,偶尔批量查询
- 时间是第一维度:几乎所有查询都带时间范围
- 历史数据价值递减:近期数据比几年前的数据更有价值,老数据可以降精度存储
- 数据量巨大:一个项目可能每天产生数亿条记录
二、为什么不用 MySQL?
MySQL 当然可以存时序数据,但存在明显短板:
| 问题 | 说明 |
|---|---|
| 写入性能瓶颈 | 高频写入时,索引维护开销大 |
| 存储空间大 | 没有针对时序数据的压缩算法 |
| 聚合查询慢 | GROUP BY time 这类时间窗口聚合不是 MySQL 的强项 |
| 数据生命周期管理缺失 | 没有内置的数据过期、降采样机制 |
时序数据库针对这些问题做了专项优化。
三、InfluxDB:专为时序而生
基本介绍
InfluxDB 是目前最流行的开源时序数据库,由 InfluxData 公司开发,完全为时序场景设计,不依赖任何关系型数据库。
核心概念
InfluxDB 有自己的一套术语体系:
- Measurement :类似数据库中的表,比如
cpu_usage、temperature - Tag :用于标识数据来源的标签,会建索引,如
host=server01,适合过滤 - Field :实际的度量值,如
value=78.5,不建索引 - Point:一条完整的数据记录(时间戳 + Tags + Fields)
写入示例
InfluxDB 使用 Line Protocol 格式写入数据:
# 格式:measurement,tag_key=tag_value field_key=field_value timestamp
cpu_usage,host=server01,region=beijing value=78.5 1704067200000000000
temperature,station=A temp=12.3,humidity=65 1704067200000000000
查询示例
InfluxDB 3.x 已支持 SQL,早期版本使用 Flux 语言:
-- 查询最近 1 小时 server01 的 CPU 均值
SELECT mean(value)
FROM cpu_usage
WHERE host = 'server01'
AND time >= now() - interval '1 hour'
GROUP BY time(5m) -- 每 5 分钟一个聚合点
特色功能
- 内置数据保留策略(Retention Policy):自动删除超过指定时间的旧数据
- 连续查询(Continuous Query):定时对原始数据降采样,自动生成低精度聚合数据
- 生态完整:原生集成 Telegraf(采集)、Grafana(展示)
四、TimescaleDB:PostgreSQL 的时序扩展
基本介绍
TimescaleDB 不是一个独立的数据库,而是 PostgreSQL 的扩展插件。它在 PostgreSQL 之上增加了时序优化能力,同时完整保留了 PostgreSQL 的所有功能。
核心概念:超表(Hypertable)
TimescaleDB 的关键创新是超表 。你创建一张普通的 PostgreSQL 表,然后将其转换为超表,TimescaleDB 会在底层自动按时间将数据切分成多个分块(Chunk),每个分块是一个独立的小表。
这样做的好处是:查询某个时间范围时,只需扫描对应的分块,而不是全表扫描。
-- 创建普通表
CREATE TABLE sensor_data (
time TIMESTAMPTZ NOT NULL,
sensor_id TEXT,
temperature DOUBLE PRECISION,
humidity DOUBLE PRECISION
);
-- 转换为超表,按时间自动分块
SELECT create_hypertable('sensor_data', 'time');
-- 之后正常插入数据,和 PostgreSQL 完全一样
INSERT INTO sensor_data VALUES (NOW(), 'sensor_A', 12.3, 65.0);
查询示例
TimescaleDB 完全兼容 SQL,还提供了一些时序专用函数:
-- 查询最近 1 小时每 5 分钟的平均温度
SELECT time_bucket('5 minutes', time) AS bucket,
sensor_id,
avg(temperature) AS avg_temp
FROM sensor_data
WHERE time >= NOW() - INTERVAL '1 hour'
AND sensor_id = 'sensor_A'
GROUP BY bucket, sensor_id
ORDER BY bucket;
特色功能
- 完整 SQL 支持:JOIN、子查询、事务、外键,PostgreSQL 能做的都能做
- 压缩:列式压缩,存储空间可减少 90% 以上
- 持续聚合(Continuous Aggregates):类似物化视图,自动维护聚合结果
- 数据分层存储:热数据留本地,冷数据自动迁移到对象存储
五、两者对比
| 维度 | InfluxDB | TimescaleDB |
|---|---|---|
| 底层架构 | 独立数据库 | PostgreSQL 扩展 |
| 查询语言 | SQL(新版)/ Flux(旧版) | 标准 SQL |
| 学习成本 | 中(需学习特有概念) | 低(会 SQL 即可上手) |
| 纯时序写入性能 | 更高 | 略低 |
| 关系查询能力 | 弱(无 JOIN) | 强(完整 SQL) |
| 数据生命周期管理 | 内置,开箱即用 | 需配置,功能完整 |
| 与现有 PG 系统集成 | 需要单独部署 | 直接复用已有 PG |
| 社区与生态 | 成熟,Grafana 原生支持 | 成熟,PostgreSQL 生态 |
| 适合数据规模 | 超大规模(亿级/天) | 大规模(千万~亿级/天) |
六、选型建议
选 InfluxDB,如果你:
- 场景非常纯粹:只需要存时序数据,不需要关联查询
- 数据量极大,对写入性能要求极高
- 团队愿意学习 Flux 或接受新版 SQL
- 需要开箱即用的数据生命周期管理
选 TimescaleDB,如果你:
- 团队已有 PostgreSQL 经验,迁移成本低
- 时序数据需要和其他业务数据做 JOIN 关联查询
- 希望在一个数据库里同时处理时序和关系型数据
- 对 SQL 标准兼容性有严格要求
一个实际判断思路:
如果你的项目里,时序数据是独立存在 的(比如纯粹的监控系统、IoT 数据平台),选 InfluxDB。 如果时序数据需要和业务数据协同(比如把传感器数据和设备档案、工单系统关联分析),选 TimescaleDB。
总结
时序数据库解决的核心问题是:让高频、海量的时间序列数据能被快速写入、高效查询、低成本存储。
InfluxDB 和 TimescaleDB 都是这个领域的优秀选手,没有绝对的优劣,只有是否适合你的场景。选型时优先考虑团队的技术栈背景和业务的数据关系复杂度,而不是追求性能数字上的极致。