时序数据库基础:从一张表说起
大家好,我是老张。今天咱们聊聊时序数据库的基础。说实话,我第一次接触时序数据库的时候,心里也犯嘀咕:这不就是个带时间戳的数据库吗?后来踩了不少坑,才明白事情没那么简单。
时序数据库到底是什么?
先给个定义。时序数据库,全称 Time Series Database,简称 TSDB。它专门用来处理带时间标签的数据。说白了,就是每一行数据都绑着一个时间戳。
我习惯这么理解:普通数据库像一本相册,记录的是某个时刻的状态。时序数据库像一部录像机,记录的是连续的变化过程。
举个例子。你记录今天的气温是25度,这是状态。但你记录从早上8点到晚上8点,每5分钟的气温变化,这就是时序数据。
核心定义:时序数据库是专门为处理带时间戳的、按时间顺序到达的数据而设计的数据库系统。
跟传统关系型数据库的区别
很多新手会问:我用 MySQL 加个时间字段不就行了?嗯,我以前也这么想过。后来在项目中处理百万级传感器数据时,MySQL 直接卡死了。
咱们用一张表来对比:
| 对比维度 | 传统关系型数据库 | 时序数据库 |
|---|---|---|
| 数据模型 | 表结构固定,强调关系 | 时间戳+标签+字段,灵活 |
| 写入模式 | 随机写入,支持事务 | 顺序写入,追加为主 |
| 查询模式 | 随机查询,关联查询 | 按时间范围扫描,聚合查询 |
| 存储优化 | 行式存储为主 | 列式存储,压缩率高 |
| 典型场景 | 电商、ERP、CRM | 监控、IoT、金融行情 |
你想想看,关系型数据库的设计初衷是保证数据的一致性和完整性。但时序数据有个特点:一旦写入,几乎不会修改。这就给了我们很大的优化空间。
我的经验:如果你要存储的数据量超过100万条/天,而且主要是追加写入,那就别用关系型数据库了。我曾经用 MySQL 存了3个月的监控数据,查询一次要等30秒。换成时序数据库后,同样的查询不到1秒。
核心概念:时间戳、度量、标签、字段
这四个概念是时序数据库的基石。我建议你牢牢记住,因为后面所有内容都围绕它们展开。
1. 时间戳(Timestamp)
时间戳就是数据产生的时间点。它必须是唯一的,或者至少是排序的。为什么?因为时序数据库的索引就是基于时间戳构建的。
格式上,我建议统一用 Unix 时间戳(毫秒级)。为什么?因为跨时区、跨系统时,时间戳最不容易出错。我曾经在项目中吃过时区的亏,后来就学乖了。
// 推荐的时间戳格式
// Unix 毫秒时间戳
timestamp: 1700000000000
// 对应的可读时间
2023-11-14 12:00:00 UTC
2. 度量(Metric)
度量就是你要测量的指标。比如 CPU 使用率、内存占用、股票价格。一个度量通常对应一个时间序列。
我习惯把度量理解成「你要观察的对象」。比如监控服务器,度量就是 cpu_usage、memory_usage、disk_io。每个度量都有自己的时间序列。
注意:度量名称要规范。我见过有人用中文、特殊字符,结果查询时各种报错。建议全小写+下划线,比如 server_cpu_usage。
3. 标签(Tag)
标签是用来描述度量属性的键值对。比如服务器 ID、机房位置、操作系统版本。标签的作用是过滤和分组。
举个例子。你监控了100台服务器的 CPU 使用率。如果没有标签,你只能看到一堆数字。加上标签后,你可以查「北京机房所有服务器的 CPU 使用率」或者「Linux 服务器的平均 CPU 使用率」。
// 标签示例
metric: cpu_usage
tags:
- host: server-01
- region: beijing
- os: linux
timestamp: 1700000000000
value: 45.2
这里有个坑:标签的值不要太多。我曾经见过一个项目,标签有50多个维度,结果索引膨胀得厉害。一般来说,标签控制在5-10个比较合适。
4. 字段(Field)
字段就是实际存储的数值。它可以是浮点数、整数、字符串甚至布尔值。字段是时序数据库真正存储的数据。
我习惯把字段分成两类:
- 数值字段:比如温度、压力、速度。这类字段支持聚合运算(求和、平均、最大最小)。
- 字符串字段:比如状态码、日志信息。这类字段只能做精确匹配。
避坑指南:我曾经在项目中把状态码(比如 "200"、"404")存成了字符串字段。结果做聚合查询时,数据库报错说无法对字符串求和。后来我改成整数类型,问题就解决了。所以,能用数值就别用字符串。
一张图看懂时序数据库的核心逻辑
下面这张 SVG 图展示了时序数据库的核心数据模型。我画这张图的时候,特意把时间戳放在最左边,因为它是所有数据的起点。
从这张图你能看到,时序数据库的数据模型是扁平的。没有复杂的表关联,没有外键约束。就是时间戳打头,后面跟着度量、标签、字段和值。这种设计让写入和查询都变得非常快。
一个完整的例子
说了这么多,咱们看个实际例子。假设你在监控一台服务器的运行状态:
// 一条完整的时序数据
{
"timestamp": 1700000000000,
"metric": "server_status",
"tags": {
"host": "web-01",
"region": "beijing",
"os": "ubuntu-22.04"
},
"fields": {
"cpu_usage": 45.2,
"memory_usage": 78.5,
"disk_io": 1024,
"status": "running"
}
}
这条数据告诉你:在某个时间点,北京机房的 web-01 服务器,CPU 用了45.2%,内存用了78.5%,磁盘IO是1024,状态是运行中。
你想想看,如果1000台服务器每5秒上报一次这样的数据,一天就是1728万条。用传统数据库,光是写入就够呛。但时序数据库可以轻松处理,因为它做了很多优化。
我的建议:刚开始学习时,先别管复杂的查询语法。先把这四个概念搞清楚。我见过太多人一上来就学各种函数,结果连数据模型都没搞明白,最后写出来的查询效率极低。
小结
这一章我们聊了时序数据库的定义、跟关系型数据库的区别,以及四个核心概念。说白了,时序数据库就是为时间序列数据量身定做的存储引擎。它牺牲了关系型数据库的灵活性,换来了极高的写入性能和查询效率。
下一章,我们会深入时序数据库的存储引擎,看看它到底是怎么做到这么快的。到时候我会分享一些我在实际项目中遇到的存储优化案例。
公众号:蓝海资料掘金营,微信deep3321