从零理解:什么是时序数据库、怎么用、什么场景该用
一句话:带时间戳的数据,按时间顺序不断追加。
你身边到处都是:
张三的薪资从15000改成18000,旧值就没了。关注的是当前状态。
15000 这个历史值消失了
每秒追加一条新记录,从来不改旧数据。关注的是变化趋势。
三个值都保留,画出一条线
| 需求 | MySQL 怎么做 | 时序库怎么做 |
|---|---|---|
| 记录服务器CPU | INSERT 一条,下次 UPDATE 覆盖 | 每次 INSERT 追加一条,永不覆盖 |
| 查当前温度 | SELECT 最新那一行 | SELECT LAST(value) |
| 查最近1小时平均 | 需要额外表存历史,再 AVG | MEAN(value) WHERE time > now() - 1h |
| 清理旧数据 | DELETE WHERE time < ...(慢) | 自动过期,配置保留策略即可 |
| 每秒写入量 | 几百到几千行/秒就吃力 | 几十万到百万行/秒很轻松 |
时序数据库的一条数据由三部分组成:
一条时序记录的结构:
时间戳:这条数据是什么时候产生的(必须有)
测量值:你要记录的数字,比如温度36.5、CPU 85%
标签:描述性信息,比如哪台机器、哪个机房(用于筛选分组)
用图书馆来类比就很好懂了:
| 时间戳 | 测量值(field) | 标签1:门店 | 标签2:品类 | 标签3:规格 |
|---|---|---|---|---|
| 2024-06-01 10:00 | 金额=18 | 门店=朝阳店 | 品类=图书馆 | 规格=大杯 |
| 2024-06-01 10:02 | 金额=22 | 门店=海淀店 | 品类=图书 | 规格=标准 |
| 2024-06-01 10:05 | 金额=15 | 门店=朝阳店 | 品类=咖啡 | 规格=小杯 |
| 2024-06-01 10:08 | 金额=28 | 门店=朝阳店 | 品类=图书馆 | 规格=大杯 |
| 2024-06-01 10:12 | 金额=18 | 门店=海淀店 | 品类=图书馆 | 规格=标准 |
温湿度传感器每5秒上报一次,你要看"客厅最近24小时温度曲线"
数据特点:写入频繁、不改历史、按时间查趋势
每台机器每秒报CPU/内存/磁盘,几十台机器 = 几百数据点/秒
数据特点:海量写入、实时聚合、自动过期
每辆车每秒报GPS位置、车速、油耗,百万辆车 = 百万点/秒
数据特点:超大规模写入、按车辆分组、轨迹回放
股票/币价每秒甚至每毫秒一个价格,K线图需要按分钟聚合
数据特点:极高频率、降采样需求强
每笔借书单带时间戳,分析"哪个时段、哪个门店、哪个品类卖得好"
数据特点:有标签(门店/品类)、有测量值(金额)
手环每秒记心率、步数,App展示"本周运动趋势"
数据特点:个人数据量不大,但用户量多时总量惊人
InfluxDB 是最流行的时序数据库,它的写入语法叫 Line Protocol,一行就是一条数据:
| 部分 | 内容 | 含义 |
|---|---|---|
| 测量名 | orders | 类似 MySQL 的表名 |
| 标签 | store=朝阳店, category=图书馆, size=大杯 | 类似 MySQL 的维度列,用于 WHERE / GROUP BY |
| 字段 | amount=18 | 类似 MySQL 的数值列,用于 SUM / AVG / MAX |
| 时间戳 | 1717203600000000000 | 纳秒级 Unix 时间戳,这条数据的时间 |
InfluxDB 的查询语言叫 InfluxQL,语法跟 SQL 非常像,但专门为时序数据优化了。
| time | store | category | size | amount |
|---|---|---|---|---|
| 2024-06-01 10:00:00 | 朝阳店 | 图书馆 | 大杯 | 18 |
| 2024-06-01 10:08:00 | 朝阳店 | 图书馆 | 大杯 | 28 |
| 2024-06-01 10:22:00 | 朝阳店 | 图书馆 | 标准 | 15 |
| store | SUM(amount) |
|---|---|
| 朝阳店 | 133 |
| 海淀店 | 91 |
| store | category | COUNT | SUM |
|---|---|---|---|
| 朝阳店 | 图书馆 | 3 | 61 |
| 朝阳店 | 咖啡 | 1 | 15 |
| 朝阳店 | 图书 | 2 | 57 |
| 海淀店 | 图书馆 | 2 | 33 |
| 海淀店 | 图书 | 2 | 38 |
| 海淀店 | 咖啡 | 1 | 20 |
GROUP BY store — 按列分组GROUP BY "store" — 按标签分组(标签是预索引的,更快)GROUP BY time(1h) — 按时间段分组(MySQL做不到!)
这是时序数据库最强大的功能,MySQL 很难做到:
| 时间区间 | SUM(amount) | 💡 说明 |
|---|---|---|
| 2024-06-01 08:00 | 95 | 8点-9点所有借书单金额加总 |
| 2024-06-01 09:00 | 132 | 9点-10点所有借书单金额加总 |
| 2024-06-01 10:00 | 158 | 10点-11点所有借书单金额加总 |
| 2024-06-01 11:00 | 110 | 11点-12点所有借书单金额加总 |
原始数据是每5秒一条,查1年趋势图 = 630万条数据,浏览器都画不出来。怎么办?
1. 原始表每5秒一条,1年 = 630万行
2. 查询时临时聚合:GROUP BY DATE_FORMAT(time, '%Y-%m-%d %H:00')
3. 每次查询都要扫描630万行再聚合,很慢
1. 用连续查询自动把5秒数据聚合成1小时数据,存到另一张表
2. 查趋势时直接查1小时表,1年 = 8760行
3. 查询速度快几百倍,存储还更省
| 阶段 | 精度 | 1年数据量 | 用途 |
|---|---|---|---|
| 原始数据 | 5秒一条 | 6,307,200 行 | 查最近几分钟的详情 | 1分钟聚合 | 1分钟一条 | 525,600 行 | 查最近几小时 |
| 1小时聚合 | 1小时一条 | 8,760 行 | 查最近几天的趋势 |
| 1天聚合 | 1天一条 | 365 行 | 查月度/年度报表 |
连续查询 = 定时自动执行的聚合查询,把原始数据的结果写到另一张表里。
| time | store | category | total | cnt | avg_amount |
|---|---|---|---|---|---|
| 2024-06-01 08:00 | 朝阳店 | 图书馆 | 95 | 5 | 19.0 |
| 2024-06-01 08:00 | 海淀店 | 图书 | 82 | 4 | 20.5 |
| 2024-06-01 09:00 | 朝阳店 | 图书馆 | 132 | 7 | 18.9 |
| 2024-06-01 09:00 | 海淀店 | 图书 | 76 | 3 | 25.3 |
时序数据量增长很快,不可能永远存着。保留策略 = 自动删除N天前的数据。
| 数据层级 | 保留策略 | 精度 | 存多久 | 查询场景 |
|---|---|---|---|---|
| 原始数据 | rp_30d | 5秒 | 30天 | 最近几分钟的实时监控 |
| 1分钟聚合 | rp_30d | 1分钟 | 30天 | 最近几小时的详情 |
| 1小时聚合 | rp_1y | 1小时 | 1年 | 最近几天的趋势图 |
| 1天聚合 | rp_1y | 1天 | 1年 | 月度/年度报表 |
| 你的需求 | MySQL | 时序库 (InfluxDB/TDengine) | 说明 |
|---|---|---|---|
| 每秒写入 < 100条 | ✅ 够用 | ✅ 也行 | 量小的话 MySQL 就够了 |
| 每秒写入 > 1000条 | ❌ 吃力 | ✅ 轻松 | 时序库的写入是 MySQL 的 10-100倍 |
| 需要 JOIN 多表 | ✅ 强项 | ❌ 不支持 | 时序库基本不能 JOIN |
| 需要事务 (ACID) | ✅ 强项 | ❌ 不支持 | 转账、下单必须用 MySQL |
| 查趋势/时间范围 | ⚠️ 能做但慢 | ✅ 专门优化 | 时序库按时间索引,极快 |
| 自动过期旧数据 | ❌ 需手动 | ✅ 内置 | 时序库配个保留策略就行 |
| 降采样/预聚合 | ❌ 需自己写 | ✅ 连续查询 | 时序库自动完成 |
| 频繁 UPDATE 单条 | ✅ 强项 | ❌ 不适合 | 时序数据几乎不 UPDATE |
| 数据库 | 语言/产地 | 查询语言 | 特点 | 适用场景 |
|---|---|---|---|---|
| InfluxDB | 美国/开源 | InfluxQL / Flux | 最流行,社区大,云托管方便 | 通用监控、IoT、运维 |
| TDengine | 中国/开源 | 类SQL | 超快写入速度,中文文档好 | 工业IoT、车联网、金融 |
| TimescaleDB | 美国/开源 | 标准SQL | PostgreSQL扩展,SQL兼容 | 已有PG经验、需要SQL生态 |
| Prometheus | 开源/CNCF | PromQL | K8s监控标配,拉模式采集 | 容器/云原生监控 |
| QuestDB | 开源 | SQL | 超快,零依赖,适合嵌入式 | 金融行情、高性能场景 |
| 概念 | 一句话 | MySQL 类比 |
|---|---|---|
| 时间戳 | 每条数据必须有,代表"什么时候发生的" | DATETIME 列 |
| 标签 (tag) | 描述性维度,用来筛选分组(索引) | WHERE / GROUP BY 的列 |
| 测量值 (field) | 数值,用来聚合计算 | SUM / AVG 的列 |
| 测量名 (measurement) | 一类时序数据的名字 | 表名 |
| 降采样 | 5秒→1分钟→1小时,精度降低但省空间 | 手动 GROUP BY + INSERT 到另一张表 |
| 连续查询 | 定时自动聚合,结果写到另一张表 | Event / cron 定时任务 |
| 保留策略 | 数据自动过期,N天后删除 | 手动 DELETE + 写脚本 |