2. 关系型数据库选型:MySQL vs PostgreSQL vs TimescaleDB
做行情数据库,第一个绕不开的问题就是:选哪个关系型数据库?
我见过不少团队,上来就用MySQL,理由是“大家都用”、“生态好”。结果跑了一段时间,查询越来越慢,存储空间暴涨,最后不得不迁移。说实话,这种坑我踩过不止一次。
今天我就把MySQL、PostgreSQL、TimescaleDB这三兄弟拉出来,针对时序数据的特性,做个硬核对比。最后告诉你,为什么我最终选了TimescaleDB。
2.1 时序数据的“脾气”
先聊聊时序数据的特点。你想想看,行情数据跟普通业务数据,本质区别在哪?
- 写入量大:每秒成千上万条tick数据,持续不断
- 时间有序:数据天然按时间戳排列,很少修改
- 查询模式固定:按时间范围查、聚合查、最新值查
- 数据生命周期:老数据需要压缩或归档
这些特性,决定了通用关系型数据库如果不做特殊优化,很难扛得住。
2.2 MySQL:熟悉的陌生人
MySQL我用了很多年,确实顺手。但用在行情场景下,问题不少。
MySQL的短板
- 没有原生时序支持:分区表功能有限,只能按RANGE分区,管理起来很麻烦
- 写入瓶颈明显:InnoDB的B+树在大量并发写入时,页分裂严重,性能下降快
- 压缩能力弱:行式存储,数据膨胀严重。我见过一个项目,1TB的行情数据在MySQL里占了3TB空间
- 时间窗口查询慢:没有针对时间序列的索引优化,全表扫描是常事
我记得有一次,帮一个量化团队做性能诊断。他们的MySQL库存了半年的1分钟K线,查询最近3天的数据要花20秒。后来我一看,连时间戳索引都没建对。但即便建了索引,MySQL在处理“按时间范围聚合”这种查询时,依然力不从心。
避坑指南:我曾经见过有人用MySQL的event scheduler做数据归档,结果因为表锁导致写入中断,丢了整整2小时的行情数据。如果你非要用MySQL,务必用pt-online-schema-change这类工具做DDL操作。
2.3 PostgreSQL:能力更强,但还不够
PostgreSQL比MySQL强不少,尤其在扩展性和数据类型上。
| 特性 | MySQL | PostgreSQL |
|---|---|---|
| 分区表 | 有限支持(5.7后改善) | 原生支持,声明式分区 |
| 索引类型 | B+Tree为主 | B+Tree、Hash、GiST、GIN、BRIN |
| 并行查询 | 8.0后支持,较弱 | 原生并行,支持并行聚合 |
| 扩展性 | 插件少 | 丰富,TimescaleDB就是其扩展 |
PostgreSQL的BRIN索引,对时序数据特别友好。它按数据块记录最大值和最小值,对于按时间范围查询的场景,能大幅减少扫描量。我做过测试,1亿条tick数据,BRIN索引比B+Tree索引小100倍,查询速度反而更快。
但PostgreSQL也有硬伤:
- 没有自动分区管理:你得自己写脚本创建、删除分区
- 压缩需要额外插件:比如cstore_fdw,配置复杂
- 连续聚合不支持:做1分钟K线聚合,你得自己写定时任务
说白了,PostgreSQL是个好底子,但针对时序场景,它缺了“最后一公里”的优化。
2.4 TimescaleDB:专为时序而生
TimescaleDB是PostgreSQL的一个扩展,但它不是简单的“插件”,而是从架构层面重新设计了存储和查询引擎。
TimescaleDB的核心优势
- 自动分区(Hypertable):按时间和空间自动分块,你只管写入,它帮你管理
- 原生压缩:列式压缩,压缩比可达10:1。我实测过,1TB的tick数据压缩后不到120GB
- 连续聚合(Continuous Aggregates):自动维护物化视图,查询K线数据毫秒级返回
- 数据保留策略:自动删除过期数据,不用写cron job
- 完全兼容PostgreSQL:所有PG生态工具都能用
下面这张图,展示了TimescaleDB的核心架构:
2.5 实战对比:一个真实的性能测试
我之前带团队做过一个对比测试,数据量是1亿条tick数据,包含时间戳、合约代码、最新价、成交量、持仓量五个字段。
| 测试项 | MySQL 8.0 | PostgreSQL 15 | TimescaleDB 2.12 |
|---|---|---|---|
| 写入速度(条/秒) | 8,000 | 15,000 | 45,000 |
| 存储空间(原始1TB) | 2.8TB | 1.5TB | 120GB(压缩后) |
| 查询最近1小时数据 | 12.3秒 | 3.1秒 | 0.8秒 |
| 生成1分钟K线(1天数据) | 45秒 | 18秒 | 0.2秒(连续聚合) |
| 删除30天前数据 | 需要手动DROP | 需要手动DROP | 自动策略,秒级 |
看到这个结果,你应该明白我为什么选TimescaleDB了。
个人经验:我建议你在选型时,不要只看基准测试。还要考虑运维成本。TimescaleDB的自动分区和保留策略,能帮你省掉至少一个DBA的工作量。我现在的团队,行情数据库就我一个人在管,完全忙得过来。
2.6 什么时候不该用TimescaleDB?
当然,TimescaleDB也不是万能的。我遇到过几个场景,它并不合适:
- 数据量极小:每天不到100万条,MySQL完全够用,没必要上TimescaleDB
- 需要复杂JOIN:如果你的行情数据需要频繁关联用户表、订单表,TimescaleDB的优势不明显
- 团队PG经验为零:如果团队只会MySQL,强行上TimescaleDB,学习成本可能比收益高
但话说回来,如果你做的是正经的行情系统,数据量迟早会上去。我个人习惯是,一开始就用TimescaleDB,省得以后迁移。
2.7 小结
选型这件事,没有银弹。但针对时序数据,TimescaleDB在写入性能、存储效率、查询速度、运维便捷性四个维度上,都明显优于MySQL和原生PostgreSQL。
我最终选择TimescaleDB,不是因为它“最流行”,而是因为它解决了行情场景下最痛的问题:海量数据的写入和存储。你想想看,如果每天几亿条tick数据进来,MySQL早就挂了,而TimescaleDB还能跑得稳稳的。
下一章,我会详细讲TimescaleDB的安装配置和Hypertable设计,包括我踩过的那些坑。嗯,到时候再细聊。