上周刚交付完一个日增数据量约 8000 万的物联网平台项目,选型阶段我们在 MySQL、PostgreSQL 和 TiDB 之间来回拉扯了近两周。作为全程参与评审和落地的 SRE,我想把这次踩过的坑和最终决策逻辑记录下来,给正在做类似选型的同学一些参考。
一、为什么会有这次对比
项目背景很典型:设备上报数据写入频繁,业务侧既要支持实时聚合查询,又要保留明细供后续分析。初期预估单表日增 500 万行,一年后接近 20 亿。团队原有技术栈以 MySQL 为主,但这次数据增长速度让我们不得不重新评估。
我们定了四个硬指标:写入吞吐、水平扩展能力、运维复杂度、生态成熟度。围绕这四点,三套方案各跑了一轮压测。
二、MySQL:熟悉但需要提前规划
MySQL 8.0 是我们最熟悉的。压测时用 sysbench 跑 oltp_write_only,单实例 16C32G + NVMe,能稳定在 1.2 万 TPS 左右。
sysbench oltp_write_only --mysql-host=10.0.1.10 \ --mysql-user=bench --mysql-password=xxx \ --tables=10 --table-size=5000000 \ --threads=64 --time=300 run
问题出在单表膨胀后。当单表超过 8000 万行,二级索引维护成本明显上升,DDL 操作即使走 Online DDL 也会出现秒级抖动。我们的应对方案是分区表 + 归档:
ALTERTABLE device_metricPARTITIONBYRANGE (TO_DAYS(create_time)) (PARTITION p202501 VALUES LESS THAN (TO_DAYS('2025-02-01')),PARTITION p202502 VALUES LESS THAN (TO_DAYS('2025-03-01')));
分区确实缓解了查询压力,但跨分区聚合仍然慢。而且分库分表中间件(如 ShardingSphere)引入后,运维复杂度陡增,跨片 JOIN 和分布式事务都要业务侧妥协。结论:MySQL 适合数据量可控、团队熟悉度优先的场景,但需要提前设计好分片和归档策略。
三、PostgreSQL:功能强大,调优有门槛
PostgreSQL 16 在复杂查询和 JSON 支持上确实亮眼。我们用同样的数据模型建表,写入压测时发现默认设置下 WAL 成为瓶颈,TPS 只有 6000 左右。调整后提升明显:
# postgresql.conf 关键调整shared_buffers = 8GBwal_buffers = 64MBmax_wal_size = 16GBcheckpoint_timeout = 30minsynchronous_commit = off
调整后写入接近 1.1 万 TPS,和 MySQL 打平。但 PostgreSQL 的 autovacuum 在超高写入场景下需要精细调参,否则表膨胀会拖慢查询。我们当时的监控看板里专门加了 pg_stat_user_tables 的 dead tuple 比例告警。
另一个坑是分区表。PostgreSQL 的声明式分区在 16 版本已经好用很多,但创建分区仍需手动或借助 pg_partman:
CREATETABLE device_metric_202502PARTITIONOF device_metricFORVALUESFROM ('2025-02-01') TO ('2025-03-01');
结论:PostgreSQL 在复杂查询和扩展性上优势明显,但需要团队有较强的调优能力,否则容易在写入高峰翻车。
四、TiDB:扩展性好,但要接受架构复杂度
TiDB 是我们最终选择的方向,核心原因是它的水平扩展能力。压测时用 3 TiKV + 3 PD + 2 TiDB 的集群,写入轻松跑到 3 万 TPS 以上,而且加 TiKV 节点就能线性提升。
搭建用 TiUP 比较顺:
tiup cluster deploy tidb-prod v7.5.0 topology.yaml --user tidbtiup cluster start tidb-prod
但 TiDB 的坑在于:它不是一个“装完就能跑”的数据库。我们遇到两个典型问题。
第一,热点问题。设备 ID 作为主键时,写入集中在少数 Region。解决方案是用 AUTO_RANDOM 或业务侧加盐:
CREATETABLE device_metric ( id BIGINT AUTO_RANDOM, device_id VARCHAR(64), ...);
第二,统计信息收集。TiDB 的优化器依赖统计信息,我们设置了定时收集:
SETGLOBAL tidb_auto_analyze_start_time ='01:00 +0000';SETGLOBAL tidb_auto_analyze_end_time ='05:00 +0000';
另外 TiDB 的监控体系基于 Prometheus + Grafana,指标非常全,但初次上手需要花时间理解 Region、Leader、Store 这些概念。结论:TiDB 适合数据量持续增长、需要在线扩展的场景,但团队要愿意投入学习成本。
五、最终决策与落地效果
我们最终选了 TiDB 作为主存储,MySQL 保留作为设置库和低频业务库,PostgreSQL 用于报表分析侧。上线三个月,写入峰值 4.2 万 TPS,P99 查询延迟稳定在 80ms 以内。扩容过一次,加了一个 TiKV 节点,业务无感知。
如果让我给一句话建议:数据量在千万级、团队 MySQL 经验足,别折腾;数据量上亿且持续增长、愿意投入学习,TiDB 值得;复杂查询多、团队有 PG 底子,PostgreSQL 很香。 选型没有银弹,只有匹配当前阶段的最优解。
这次交付最大的体会是:数据库选型不是比谁参数漂亮,而是比谁能在你的业务曲线和团队能力之间找到平衡点。希望这篇排坑记能帮你少走一段弯路。
👨💻 运维老兵经验:根据实际生产环境,以上步骤建议先在测试环境验证,并做好备份。参数值需根据服务器设置调整,不要盲目照搬。