引言:你是否正在为时序数据“焦头烂额”?
你是否遇到过这样的问题:
在大数据时代,时序数据(按时间顺序生成的数据,比如监控指标、IoT传感器、日志)已经成为业务的核心资产。但传统数据库(如MySQL、PostgreSQL)天生不适合处理时序数据——它们的索引和存储结构是为“事务”设计的,而不是为“高写入、低延迟时间查询”设计的。
这时候,你需要时序数据库(Time Series Database,TSDB)——一种专门为时序数据优化的数据库。但市场上的时序数据库种类繁多,InfluxDB、ClickHouse、TDengine、TimescaleDB、Prometheus……到底该选哪一个?
本文将帮你解决这个问题:
读完本文,你将能:
在开始选型前,先确认你具备以下基础:
选时序数据库前,先回答这5个问题,避免“为技术而技术”:
关键影响:数据库的写入吞吐量——大规模场景需要支持高并发写入的数据库(比如ClickHouse、TDengine)。
关键影响:数据库的写入优化策略——高并发场景选支持“写入队列”的数据库(比如TDengine),批量导入选支持“CSV/Parquet导入”的数据库(比如ClickHouse)。
关键影响:数据库的查询引擎优化方向——实时查询选“内存优先”的数据库(比如Prometheus),复杂聚合选“列式存储”的数据库(比如ClickHouse)。
关键影响:生态兼容性——避免“重新造轮子”,复用现有工具能节省大量时间。
关键影响:运维复杂度
——避免选择那些需要“资深数据库管理员”才能操作的数据库(例如ClickHouse),如果您的团队缺乏维护经验。
现在,我们进入核心部分——深入探讨5种主要的时序数据库,每个方案涵盖:
InfluxDB是时序数据库领域的“老玩家”,2.x版本集成了 可视化(Chronograf)、流处理(Kapacitor)、存储 ,提供了一个“全方位的时序平台”。它采用了 Flux语言 代替了1.x版本的InfluxQL,更适用于时序数据的时间区间和标签筛选。
适用场景:中小型物联网(每日写入100万至5亿条记录)、监控系统、应用程序性能监控(APM); 核心匹配点: 集成体验:内置可视化和流处理,无需额外配置工具; 高度易用:Flux语言比SQL更适合时序数据查询; 活跃社区:丰富的文档资源,问题易于解决。
步骤1:使用Docker启动InfluxDB
# 拉取镜像
docker pull influxdb:2.7
# 启动容器(映射端口和数据目录)
docker run -d -p 8086:8086 \
-v ~/influxdb2:/var/lib/influxdb2 \
--name influxdb2 \
influxdb:2.7
启动后,访问
http://localhost:8086
,根据指引创建:
Organization
:组织(例如“my-org”);
Bucket
:存储桶(类似于数据库,例如“sensor-data”);
API Token
:用于身份验证(妥善保存,后续会用到)。
步骤2:写入测试数据
使用Python SDK写入(先安装
influxdb-client
:
pip install influxdb-client
):
from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS
import time
# 初始化客户端(替换为您的Token、Org、Bucket)
client = InfluxDBClient(
url="http://localhost:8086",
token="您的API Token",
org="my-org"
)
write_api = client.write_api(write_options=SYNCHRONOUS)
bucket = "sensor-data"
# 生成1000条测试数据(设备ID=1,温度25-29℃)
points = []
for i in range(1000):
point = Point("sensor_measurements") # 测量名(类似表名)
.tag("device_id", "1") # 标签(用于过滤)
.field("temperature", 25 + i%5) # 字段(测量值)
.time(int(time.time()) - i, write_precision="s") # 时间戳(秒级)
points.append(point)
# 批量写入
write_api.write(bucket=bucket, record=points)
print("写入完成!")
步骤3:查询数据
在InfluxDB UI的 Data Explorer 中,使用Flux语言查询“过去10分钟,设备ID=1的温度趋势”:
from(bucket: "sensor-data")
|> range(start: -10m) # 时间范围:过去10分钟
|> filter(fn: (r) => r._measurement == "sensor_measurements") # 过滤测量名
|> filter(fn: (r) => r.device_id == "1") # 过滤设备ID
|> filter(fn: (r) => r._field == "temperature") # 过滤字段(温度)
|> yield(name: "temperature_trend") # 返回结果
执行后,将显示温度随时间变化的折线图。
优点: 集成体验:内置可视化和流处理,无需额外配置; 高度易用:Flux语言比SQL更适合时序数据的时间区间筛选; 活跃社区:丰富的文档资源,问题易于解决。
缺点: 大规模数据限制:当单节点写入超过5亿条/天时,性能显著下降(需要集群版,成本较高); Flux学习曲线:对于习惯SQL的用户,需要时间适应; 商业版依赖:高级特性(多租户、灾难恢复)需要购买企业版。
如果您所在的场景是 中小型物联网、监控系统 ,并且希望“即插即用”,那么选择InfluxDB 2.x。
TimescaleDB并不是一个全新的数据库,而是 PostgreSQL的一个扩展 (extension)。它通过 hypertables (时间分区表)将传统的PostgreSQL转换成时序数据库,完全兼容SQL。
适用场景:已经在使用PostgreSQL的业务(例如电子商务订单的时间序列分析)、需要SQL支持的时序场景(例如“查询过去7天每位用户的登录次数”)、中小型大数据(每日写入1亿条以内); 核心匹配点: 完全兼容SQL:无需学习新的语言,直接使用PostgreSQL的SQL查询;
PostgreSQL生态系统:利用现有的PostgreSQL工具(例如pgAdmin)、驱动(例如psycopg2);
灵活的分片策略:hypertables支持依据时间和空间(例如设备ID)进行分片,增强查询效率。
docker run -d --name timescaledb -p 5432:5432 \
-e POSTGRES_PASSWORD=my-password \
timescale/timescaledb:latest-pg15
进入容器,激活TimescaleDB扩展:
docker exec -it timescaledb psql -U postgres
# 激活扩展
CREATE EXTENSION IF NOT EXISTS timescaledb;
创建一个用于存储传感器数据的表,并将其转换为hypertables:
-- 创建常规表
CREATE TABLE sensor_data (
time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
device_id INT NOT NULL,
temperature FLOAT NOT NULL,
humidity FLOAT NOT NULL
);
-- 转换为hypertables(按时间分片,每7天一个分片)
SELECT create_hypertable('sensor_data', 'time', chunk_time_interval => INTERVAL '7 days');
使用Python的
psycopg2
插入(首先安装
psycopg2-binary
:
pip install psycopg2-binary
):
import psycopg2
from datetime import datetime, timedelta
import random
# 连接数据库(替换为你的密码)
conn = psycopg2.connect(
dbname="postgres",
user="postgres",
password="my-password",
host="localhost",
port="5432"
)
cur = conn.cursor()
# 生成1000条数据(时间从现在往前推1000秒)
start_time = datetime.now() - timedelta(seconds=1000)
for i in range(1000):
time = start_time + timedelta(seconds=i)
device_id = random.randint(1, 10)
temperature = 25 + random.uniform(-2, 2)
humidity = 60 + random.uniform(-5, 5)
# 插入数据
cur.execute("""
INSERT INTO sensor_data (time, device_id, temperature, humidity)
VALUES (%s, %s, %s, %s)
""", (time, device_id, temperature, humidity))
conn.commit()
cur.close()
conn.close()
print("插入完成!")
使用SQL查询“过去5分钟,device_id=1的平均温度”:
SELECT time_bucket('1 minute', time) AS minute,
AVG(temperature) AS avg_temperature
FROM sensor_data
WHERE device_id = 1 AND time > NOW() - INTERVAL '5 minutes'
GROUP BY minute
ORDER BY minute;
执行后,将返回每1分钟的平均温度。
优点:
缺点:
如果你的团队 已经在使用PostgreSQL ,或者需要 SQL支持的时间序列场景 ,选择TimescaleDB。
ClickHouse是Yandex开源的 列式存储数据库 ,以其 极致的查询速度 著称。
知名,特别擅长大量时间序列数据的汇总分析(例如“计算最近30天各省份的设备在线率”)。
适用场景:大量时间序列分析(每日录入超过10亿条记录)、离线日志分析、实时OLAP(例如实时监控全国服务器的CPU使用率前十);
核心匹配点:
步骤1:使用Docker启动ClickHouse
docker run -d --name clickhouse-server -p 8123:8123 -p 9000:9000 \ -v ~/clickhouse/data:/var/lib/clickhouse \ yandex/clickhouse-server:latest
验证启动:访问
http://localhost:8123
,看到“Ok.”表示启动成功。
步骤2:创建时间序列表
ClickHouse的 MergeTree引擎 是时间序列数据的理想选择,支持列式存储、排序、分区:
CREATE TABLE sensor_data ( time DateTime, device_id UInt32, temperature Float32, humidity Float32 ) ENGINE = MergeTree() ORDER BY (device_id, time) -- 按设备ID和时间排序(加快查询速度) PARTITION BY toYYYYMM(time) -- 按年月分区(如202405) TTL time + INTERVAL 30 DAY; -- 自动清除30天前的数据
步骤3:写入测试数据
使用Python的
clickhouse-driver
写入(先安装:
pip install clickhouse-driver
):
from clickhouse_driver import Client
import random
from datetime import datetime, timedelta
# 连接ClickHouse
client = Client(host='localhost', port=9000)
# 生成100万条测试数据
data = []
start_time = datetime.now() - timedelta(days=7)
for i in range(1000000):
time = start_time + timedelta(seconds=i)
device_id = random.randint(1, 1000)
temperature = 25 + random.uniform(-5, 5)
humidity = 60 + random.uniform(-10, 10)
data.append((time, device_id, temperature, humidity))
# 批量写入
client.execute('INSERT INTO sensor_data VALUES', data)
print("写入完成!")
步骤4:查询数据
查询“过去7天,每台设备的平均温度”:
SELECT device_id, AVG(temperature) AS avg_temp FROM sensor_data WHERE time > now() - INTERVAL 7 DAY GROUP BY device_id ORDER BY avg_temp DESC LIMIT 10;
对于100万条数据,此查询将在 0.1秒内返回结果 。
优势:
劣势:
选型建议:
如果你的应用场景是 大规模时间序列分析、离线日志分析、实时OLAP ,请选择ClickHouse——它是该领域的“性能猛兽”。
1. 方案概述
TDengine(涛思数据)是国内开源的时间序列数据库,专为 IoT和工业大数据 设计。它引入了“超级表(Super Table)+子表(Sub Table)”的概念,通过“设备类型+设备ID”来组织数据,增强IoT场景下的写入和查询性能。
2. 大数据应用场景
适用场景
IoT设备数据(例如智能电表、工业传感器)、工业大数据(例如生产线的设备状态监控)、高并发写入场景(例如100万台设备每秒上报);
核心适配点:
3. 实战:快速上手TDengine
步骤1:用Docker启动TDengine
docker run -d --name tdengine -p 6030:6030 -p 6041:6041 -p 6043-6049:6043-6049 \
-v ~/tdengine/data:/var/lib/taos \
tdengine/tdengine:latest
验证启动:进入容器,输入
taos
,看到
Welcome to TDengine
说明成功。
步骤2:创建超级表和子表
假设我们有“智能电表”类型的设备,创建超级表(代表设备类型)和子表(代表具体设备):
-- 创建数据库
CREATE DATABASE iot_data;
USE iot_data;
-- 创建超级表(st_energy_meter:智能电表的超级表)
CREATE STABLE st_energy_meter (
ts TIMESTAMP, -- 时间戳
voltage FLOAT, -- 电压
current FLOAT, -- 电流
power FLOAT -- 功率
) TAGS (
device_id INT, -- 设备ID(子表的标签)
location VARCHAR(64) -- 设备位置(子表的标签)
);
-- 为设备ID=123创建子表(location=“北京朝阳区”)
CREATE TABLE t_energy_meter_123 USING st_energy_meter TAGS (123, "北京朝阳区");
步骤3:写入测试数据
用Python的
taosrest
写入(先安装:
pip install taosrest
):
from taosrest import connect
from datetime import datetime
# 连接TDengine(替换为你的IP和端口)
conn = connect(url="http://localhost:6041", user="root", password="taosdata")
# 写入3条数据到子表t_energy_meter_123
data = [
("t_energy_meter_123", datetime(2024,5,20,10,0,0), 220.5, 10.2, 2249.1),
("t_energy_meter_123", datetime(2024,5,20,10,0,1), 221.0, 10.3, 2276.3),
("t_energy_meter_123", datetime(2024,5,20,10,0,2), 220.8, 10.1, 2230.1)
]
# 批量插入
conn.execute_many("INSERT INTO ? VALUES (?, ?, ?, ?)", data)
print("写入完成!")
步骤4:查询数据
查询“北京朝阳区的设备,过去1分钟的平均功率”:
SELECT
device_id,
location,
AVG(power) AS avg_power
FROM st_energy_meter
WHERE location = "北京朝阳区" AND ts > NOW() - 1m
GROUP BY device_id, location;
4. 优缺点分析
优点:
缺点:
选型建议:
如果你的场景是 IoT设备数据、工业大数据、边缘计算 ,选TDengine——它是为此场景“量身定制”的。
方案五:Prometheus——监控场景的“事实标准”
1. 方案概述
Prometheus是CNCF毕业的项目,专门用于 监控系统 的时序数据库。它以“拉取(Pull)”模式收集数据(如从服务器的Node Exporter拉取CPU使用率),用 PromQL 查询,与Grafana配合实现可视化。
:云原生监控(Kubernetes集群监控)、应用性能监控(APM)、服务指标监控(例如微服务的请求延迟);
:监控优化:PromQL是专为监控设计的查询语言(例如
rate(http_requests_total[5m])计算过去5分钟的请求率);云原生集成:与Kubernetes、Docker、Istio深入集成;拉取模式:适合监控分布式的系统(例如Kubernetes的多个Pod)。
docker run -d --name prometheus -p 9090:9090 \
-v ~/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus:latest
prometheus.yml
配置文件内容(收集自己的指标):
global:
scrape_interval: 15s # 每15秒获取一次数据
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090'] # 获取Prometheus自身的指标
启动Node Exporter(收集服务器的CPU、内存指标):
docker run -d --name node-exporter -p 9100:9100 \
--net="host" \
--pid="host" \
-v "/:/host:ro,rslave" \
quay.io/prometheus/node-exporter:latest \
--path.rootfs=/host
修改
prometheus.yml,添加Node Exporter的收集配置:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node_exporter'
static_configs:
- targets: ['host.docker.internal:9100'] # 访问宿主机器的Node Exporter
重启Prometheus:
docker restart prometheus
访问
http://localhost:9090/graph,用PromQL查询“过去5分钟的CPU使用率”:
1 - avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100
此查询将返回服务器的CPU使用率百分比。
启动Grafana:
docker run -d --name grafana -p 3000:3000 grafana/grafana:latest
访问
http://localhost:3000(默认用户名/密码:admin/admin),添加Prometheus数据源(URL填写http://prometheus:9090),然后导入Grafana的Node Exporter Dashboard(ID:1860),即可查看服务器的CPU、内存、磁盘使用情况的可视化面板。
如果您的场景是云原生监控、APM、服务指标监控,选择Prometheus——它是该领域的“领导者”。
选择了合适的数据库,还需优化才能发挥最佳性能。这里分享3个大数据场景的关键优化技巧:
时间+标签为核心:将“常用于过滤条件的字段”设为标签(例如设备ID、位置),标签将被索引,查询速度更快;将“不常用于过滤的字段”设为字段(例如设备的固件版本)。
避免过度标签化:过多的标签会增大索引尺寸,降低写入性能。例如在IoT场景中,“设备类型”应作为标签,“设备的电池电量”不是常用的过滤条件,应设为字段。
时间精度适度:不要使用比所需更精细的时间精度(例如使用秒而非纳秒),以减少存储和索引的大小。
批量写入:几乎所有的时序数据库都支持批量写入(例如InfluxDB的批量API、ClickHouse的CSV导入)。批量写入可以减少网络开销和数据库的写入频率,提高吞吐量。例如IoT设备每10秒上报10条数据,而不是每秒上报1条。
避免乱序写入
时序数据按时间顺序写入可以提高存储效率(例如ClickHouse的MergeTree引擎按时间排序)。如果存在乱序写入(例如设备时间同步出错),应先校正时间再写入。
启用数据压缩
部分数据库支持数据压缩(例如ClickHouse的LZ4压缩、TDengine的Delta压缩),启用压缩可以减少磁盘占用,提升查询速度(读取的数据更少)。
技巧3:优化查询策略
必须带有时间范围
时序查询务必带有时间范围过滤(例如
time > NOW() - 1h),否则数据库会扫描所有数据,性能非常差。
使用聚合查询
对于大量数据,不要查询原始数据(例如“查过去30天的所有温度数据”),而应查询聚合后的结果(例如“查过去30天每天的平均温度”)——聚合能显著减少返回的数据量。
预计算
对于频繁查询的聚合结果(例如“每小时的平均温度”),利用数据库的预计算功能(例如InfluxDB的Task、ClickHouse的Materialized View)提前计算,查询时直接获取预计算的结果,提升速度。
至此,我们已经涵盖了5种主流时序数据库的核心内容。为了更加直观,我制作了一个选型决策树,帮助你快速找到最合适的方案:
你的场景是监控吗?
你的场景是IoT/工业大数据吗?
你已经在使用PostgreSQL吗?
你的数据量是每日写入10亿条以上吗?
你希望“开箱即用”吗?
时序数据库的选型没有“绝对正确”的答案,只有“最适合自己场景”的答案。如果你在选型或使用过程中遇到问题,欢迎在评论区留言——我会尽力为你解答!
另外,如果你有自己的时序数据库选型经验,也欢迎分享出来,帮助更多人避免陷阱!
最后,记住:
技术是为了业务服务的,不要为了“炫酷”而选择不合适的数据库——选对了,可以让你事半功倍;选错了,会让你陷入无尽的优化和调试中。
InfluxDB 2.x文档:https://docs.influxdata.com/influxdb/v2/
TimescaleDB文档:https://docs.timescale.com/
ClickHouse文档:https://clickhouse.com/docs/
TDengine文档:https://docs.taosdata.com/
Prometheus文档:https://prometheus.io/docs/
希望这篇文章能帮你找到适合自己的时序数据库!Happy coding!????
扫码加好友,拉您进群



收藏
