LOGO 首页 OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 技术文档 其他文档  
 
网站管理员

为什么我们最终选了 PostgreSQL,而不是 MySQL

admin
2026年6月12日 8:29 本文热度 239

说出来可能被喷——我们团队在 2023 年做了一个让所有人意外的决策:新系统不用 MySQL,用 PostgreSQL。

这事在技术评审会上吵了整整两轮。DBA 说"MySQL 我们熟",架构师说"PostgreSQL 的 JSONB 真的适合我们的场景",我在白板上画了三个 Venn 图,最后 CTO 拍板:先在一个子系统上试,跑半年再说。

半年后,那个子系统成了我们整个公司查询性能最好的服务。然后又过了半年,我们开始把更多新系统往 PostgreSQL 上迁移。

整个过程没有"MySQL 不好"的结论,只有"我们的场景更适合 PostgreSQL"的决策。把这个过程写下来,供你们选型时参考。

1. 背景:我们是什么场景

先说清楚我们的业务场景,因为技术选型从来没有"最好",只有"最适合"。

我们是做 B 端 SaaS 的,核心数据模型有几个特点:

  1. 结构化数据 + 半结构化数据混存:每条业务记录有固定字段(id、创建时间、状态等),但也有一个 ext_info 字段,存的是变长的业务属性,不同客户配置不一样
  2. 复杂查询多:B 端系统不像 C 端那样简单 KV 查询,经常有"筛选 + 排序 + 分页"的组合查询,条件最多的时候有 15 个
  3. 写入并发不高,但查询并发不低:峰值写入 QPS 约 500,但查询 QPS 能到 8000+
  4. 数据量中等:单表最大约 2 亿行,但大部分表在千万级

MySQL 当然能搞定这些场景,我们旧系统就是用 MySQL 5.7 跑的。但踩了一些坑之后,我们开始认真考虑 PostgreSQL。

2. 第一个原因:JSONB 改变了我们的数据建模方式

这是最直接的原因。

我们的 ext_info 字段在 MySQL 里是用 JSON 类型存的(5.7+ 支持),但用起来很憋屈:

SQL-- MySQL 里查 JSON 字段,索引不太好建
SELECT * FROM orders 
WHERE JSON_EXTRACT(ext_info, '$.industry_id'= 42
  AND JSON_EXTRACT(ext_info, '$.region_code'= 'SZ';

可以建虚拟列 + 索引,但每次 ext_info 的结构变了都要改表,对 SaaS 多租户场景来说维护成本很高。

PostgreSQL 的 JSONB 是真正为查询优化的:

SQL-- PostgreSQL: 直接建 GIN 索引,任意 JSON 路径都能走索引
CREATE INDEX idx_ext_info ON orders USING GIN (ext_info);

-- 查询:快得离谱
SELECT * FROM orders 
WHERE ext_info @> '{"industry_id": 42, "region_code": "SZ"}';

GIN 索引的酷炫之处在于:不管你在 JSONB 里怎么嵌套,只要 @> 操作符能匹配上,就能走索引。我们实测,同样是 2000 万行的表,MySQL 的 JSON 查询(带索引)平均 RT 约 120ms,PostgreSQL 的 JSONB 查询平均 RT 约 18ms。

但这不是免费午餐。 JSONB 的写入性能比普通列慢,因为 GIN 索引的维护成本比较高。好在我们的场景是"读多写少",这个权衡完全可以接受。

3. 第二个原因:CTE 和窗口函数让复杂查询不再痛苦

B 端系统经常有这种需求:“查出每个客户最近 30 天内的前 5 笔订单,按金额排序”。

MySQL 8.0 虽然支持了窗口函数,但用起来还是很啰嗦,而且性能……不太好:

SQL-- MySQL 8.0: 窗口函数写法
WITH ranked_orders AS (
  SELECT *ROW_NUMBER() OVER (
    PARTITION BY customer_id 
    ORDER BY amount DESC
  ) as rn
  FROM orders
  WHERE created_at >= NOW() - INTERVAL 30 DAY
)
SELECT * FROM ranked_orders WHERE rn <= 5;

PostgreSQL 的 CTE(公用表表达式)支持 MATERIALIZED 提示,对于多次引用同一子查询的场景性能更好。而且 PostgreSQL 的查询优化器对复杂 JOIN + 窗口函数的组合优化得更彻底——我们迁移过去之后,有一些原来需要 3 秒的报表查询,现在 400ms 就跑完了。

但这不是 PostgreSQL 单方面碾压。 MySQL 8.0 的窗口函数已经够用了,而且 MySQL 的优化器在简单查询(点到点)上其实更快。如果你的场景是"简单查询为主",MySQL 反而更合适。

4. 第三个原因:MVCC 的实现差异

这是比较底层的原因,但影响了我们的运维体验。

MySQL(InnoDB)的 MVCC 实现依赖 undo log,长事务会导致 undo log 膨胀,而且 MySQL 的 VACUUM 机制(实际上是 purge 线程)不如 PostgreSQL 的 VACUUM 来得彻底。我们有一次有一个慢查询跑了 40 分钟(是全表扫描,别喷我),导致 undo log 涨到了 60GB,后面的写入全都变慢了。

PostgreSQL 的 MVCC 实现不同,它靠 VACUUM 进程清理旧版本数据。只要你配置得当(autovacuum 参数调优),长事务对系统的影响相对可控。

但这里有个大坑: PostgreSQL 的 VACUUM 会锁表,而且默认配置下在小规格机器上可能会"抢资源"。我们刚开始用的时候没调优,VACUUM 在业务高峰期自动触发,导致 CPU 飙高。后来专门配了 autovacuum_vacuum_scale_factor = 0.05(默认是 0.2,太激进了),才算稳定下来。

5. 第四个原因:扩展生态,但不是你想的那样

很多人说"PostgreSQL 扩展多,MySQL 没有"。这个说法有点偏颇,但确实有些扩展是 PostgreSQL 独有的。

我们用了两个:

  • PostGIS:地理空间数据查询。我们有个功能是"找附近 5 公里内的客户",用 PostGIS 的 ST_DWithin 一行 SQL 搞定,性能比在应用层算距离再过滤快得多。
  • pg_stat_statements:比 MySQL 的 performance_schema 好用,可以精确看到每条 SQL 的等待时间和执行计划选择。我们用它找出了一个有问题的查询——它在 MySQL 上走的是全表扫描,但在 PostgreSQL 上优化器选了索引扫描,差距是 30 秒 vs 0.3 秒。

但反过来说,MySQL 的生态更成熟。 如果你要用到云厂商的托管服务,MySQL 的支持度(备份、恢复、监控、扩容)还是比 PostgreSQL 好不少的。我们用的是自建机房,这个问题不突出,但上云的话需要慎重。

6. 第五个原因:我们团队有人踩过 PostgreSQL 的坑

这是最实在的原因。

我们团队有个 Senior 之前在上一家公司用过 3 年 PostgreSQL,他知道:

  • 什么时候该用 partial index(部分索引)
  • 怎么调 work_mem 让复杂排序不落盘
  • 怎么用 pg_repack 在线重建表和索引而不锁表
  • 怎么用 pgBackRest 做增量备份

团队里有"踩过坑的人",这才是技术选型最重要的因素之一。 如果团队里没人懂 PostgreSQL,出了问题只能 Google,那选型的风险就太大了。

7. 我们的做法

没有"一刀切"的结论。我们的情况是:

场景选型原因
新系统,有 JSON 半结构化数据PostgreSQLJSONB + GIN 索引
复杂报表查询,多表 JOINPostgreSQL查询优化器更强
老系统,简单 CRUDMySQL不动,迁移成本太高
高并发写入场景MySQL我们实测 InnoDB 写入性能略好

实际上,我们现在的架构是 MySQL + PostgreSQL 并存的。 新系统默认用 PostgreSQL,老系统继续用 MySQL,两者之间靠应用层做数据同步(用 Debezium 抓 MySQL binlog 同步到 PostgreSQL,反过来用 pglogical)。

这个架构运行了快两年,出过问题吗?出过。PostgreSQL 的主从复制曾经因为网络抖动导致从库落后主库 30 秒,我们的读负载均衡没做好兜底,导致用户看到了旧数据。

但总体来说,这个决策我们没有后悔。

8. 选型建议

如果你也在纠结 MySQL vs PostgreSQL,问自己这几个问题:

  1. 你的场景里 JSON/半结构化数据多吗? 多 → PostgreSQL
  2. 复杂查询(多表 JOIN + 窗口函数)多吗? 多 → PostgreSQL
  3. 团队里有人懂 PostgreSQL 吗? 没有 → 慎用,或者用云托管服务
  4. 你要上云吗? 上云 + 用托管服务 → MySQL 支持更完善
  5. 写多读少,还是读多写少? 写多 → 两者差不多;读多且复杂查询多 → PostgreSQL

没有最好的数据库,只有最适合你场景的数据库。

我们放弃了"统一技术栈"的执念,根据实际场景选工具,这事到现在看来是对的。


阅读原文:https://mp.weixin.qq.com/s/FfzvWIdwyHp68SqsFPcgzw


该文章在 2026/6/12 10:50:37 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-9  粤公网安备44030602007207号