4. 时序数据库选型:Prometheus vs InfluxDB vs TimescaleDB

做量化交易系统,监控数据怎么存,是个绕不开的坎。

我个人习惯把时序数据库比作「流水账本」——每一条记录都带着时间戳,按时间顺序追加。但同样是记账,不同账本的记法、压缩方式、查询速度,差别大了去了。

今天咱们就掰开揉碎,聊聊 Prometheus、InfluxDB 和 TimescaleDB 这三兄弟。我这些年踩过的坑,全在这了。

4.1 存储模型:三种完全不同的哲学

先说存储模型。说白了就是数据在磁盘上怎么摆。

Prometheus:标签驱动的倒排索引

Prometheus 的存储模型,核心是「指标名 + 标签集」。举个例子:

trade_volume{exchange="binance", symbol="BTCUSDT", side="buy"} 12.5

每个时间序列由指标名和标签唯一确定。内部用倒排索引来加速标签查询。

我遇到过的问题:标签基数太高时,内存会爆。有一次监控了每个用户的订单延迟,标签里带了 user_id,结果几万个用户一上来,Prometheus 直接 OOM。嗯,这里要注意——标签的基数(唯一取值数量)最好控制在几千以内。

InfluxDB:列式存储 + 时间分片

InfluxDB 用的是 TSM(Time-Structured Merge Tree)引擎。数据按时间分片,每个分片内按列存储。

它的数据模型是「measurement + tag + field」。tag 是索引字段,field 是实际数值。

trade_volume,exchange=binance,symbol=BTCUSDT value=12.5 1700000000

说白了,tag 相当于 Prometheus 的标签,但 InfluxDB 对 tag 的基数容忍度更高。我有个项目跑了 10 万个 tag 组合,InfluxDB 依然稳如老狗。

TimescaleDB:关系数据库的时序扩展

TimescaleDB 是 PostgreSQL 的插件。它把数据自动按时间分区(叫 hypertable),但底层还是关系表。

CREATE TABLE trades (
    time TIMESTAMPTZ NOT NULL,
    exchange TEXT,
    symbol TEXT,
    volume DOUBLE PRECISION
);
SELECT create_hypertable('trades', 'time');

你可以直接用 SQL 查询。对于习惯关系数据库的团队,上手成本几乎为零。

我的建议:如果团队 SQL 能力强,选 TimescaleDB;如果追求原生时序能力,InfluxDB 更顺手;如果只是做 Prometheus 生态的监控,别折腾,直接用 Prometheus 自带的存储。

4.2 压缩率:磁盘空间就是钱

量化交易系统一天能产生几十 GB 的监控数据。压缩率直接决定了你的存储成本。

数据库 压缩算法 典型压缩率 实测场景(1亿条)
Prometheus Snappy + XOR(浮点) 1:8 ~ 1:12 约 2.3 GB
InfluxDB 自定义列式压缩 1:10 ~ 1:20 约 1.1 GB
TimescaleDB PG 原生 + 列式压缩 1:5 ~ 1:10 约 3.5 GB

你看,InfluxDB 的压缩率明显领先。为什么?因为它对时间戳和数值做了专门的编码优化。比如时间戳用 delta-of-delta 编码,数值用 XOR 压缩,重复值还能跑字典压缩。

我曾经踩过的坑:TimescaleDB 如果不开启列式压缩(native compression),压缩率其实很一般。记得我有个客户,用默认设置存了三个月数据,磁盘直接报警。后来开了压缩,空间省了 70%。

小技巧:TimescaleDB 的压缩是异步的,需要手动调用。建议写个定时任务,每小时压缩一次旧数据。

4.3 查询性能:快慢之间见真章

查询性能分两种场景:实时查询和历史聚合。咱们分开看。

实时查询(最近 1 小时)

Prometheus 最快。因为它把最近的数据全放在内存里,查询基本是毫秒级。InfluxDB 也很快,但需要预热缓存。TimescaleDB 稍慢,毕竟要走 PostgreSQL 的查询计划。

我做过一个压测:查询最近 5 分钟的 trade_volume 平均值。

  • Prometheus:3ms
  • InfluxDB:8ms
  • TimescaleDB:15ms

差距不大,但 Prometheus 确实占优。

历史聚合(过去 30 天)

这个场景下,TimescaleDB 反而逆袭了。因为它支持复杂的 SQL 聚合,比如按小时分组、按交易所分组、甚至做窗口函数。

SELECT time_bucket('1 hour', time) AS hour,
       exchange,
       AVG(volume) AS avg_volume
FROM trades
WHERE time > NOW() - INTERVAL '30 days'
GROUP BY hour, exchange
ORDER BY hour;

Prometheus 的 PromQL 虽然强大,但做这种多维聚合就有点吃力了。InfluxDB 的 Flux 语言能搞定,但学习曲线陡峭。

注意:Prometheus 的查询如果跨了太多时间序列,容易超时。我建议把历史聚合任务单独跑,别让告警查询和聚合查询混在一起。

4.4 选型决策树

说了这么多,到底怎么选?我画了张图,帮你快速决策。

时序数据库选型 Prometheus生态? SQL团队为主? 高基数标签? Prometheus 自带存储即可 TimescaleDB SQL灵活查询 InfluxDB 高基数友好 我的个人经验总结 • 监控告警为主 → Prometheus(生态最成熟) • 历史分析为主 → TimescaleDB(SQL 最灵活) • 高基数 + 高写入 → InfluxDB(压缩率最优) • 混合场景 → InfluxDB + Prometheus 搭配使用

4.5 我的最终建议

没有银弹。三个数据库各有千秋。

如果你只是做 Prometheus 生态的监控告警,别折腾,直接用 Prometheus 自带的存储。我见过太多人为了「统一存储」强行上 InfluxDB,结果 PromQL 用不了,还得再搭一层适配器。

如果你需要做复杂的量化分析,比如按交易所、按交易对、按时间窗口做聚合,TimescaleDB 的 SQL 能力无可替代。我有个策略回测系统,直接拿 TimescaleDB 当数据仓库用,省掉了 ETL 环节。

如果你面临高基数标签(比如每个用户一条监控线),InfluxDB 是最稳妥的选择。它的列式压缩和倒排索引,天生为这种场景设计。

避坑指南:我曾经在一个项目里同时用了 Prometheus 和 InfluxDB。Prometheus 负责实时告警,InfluxDB 负责历史存储。中间用了一个叫 prometheus-remote-storage-adapter 的组件做桥接。效果不错,但运维复杂度翻倍。小团队慎用。

好了,时序数据库选型就聊到这儿。记住一句话:选型不是选最好的,而是选最适合你场景的


公众号:蓝海资料掘金营,微信deep3321