在很长一段时间里,我的项目数据库选型几乎都是 MySQL 。
原因很简单:上手快、资料多、运维成熟,基本不会踩大坑。
但随着业务逐渐复杂,我越来越频繁地遇到一个问题:
不是 MySQL 不好,而是它开始"不够用了"。
最终,在一个核心系统中,我选择从 MySQL 迁移到 PostgreSQL 。
这篇文章不谈"谁更牛",只聊 我为什么要迁移,以及迁移之后带来的真实变化。
一、最初选择 MySQL:完全没问题
在业务初期,我的系统非常典型:
- 表结构简单
- CRUD 为主
- 查询条件固定
- 并发量不算高
这种情况下,MySQL 的优势非常明显:
- 开发效率高
- ORM 支持好
- 运维成本低
- 社区资料极其丰富
👉 在早期阶段,MySQL 是非常正确的选择。
二、问题开始出现:SQL 越来越"别扭"
随着业务发展,我开始频繁遇到下面这些需求:
- 查询条件不断变化
- 一个接口要拼十几种筛选条件
- 统计 + 排序 + 分组 + 子查询
- 一条 SQL 变得又长又难维护
在 MySQL 中,经常出现:
- SQL 写得很"绕"
- 需要多次查询再在代码里拼结果
- 某些统计逻辑不得不下沉到应用层
数据库越来越像"存储工具",而不是"计算工具"。
三、第一个痛点:复杂查询能力不足
举个很真实的例子:
用户行为统计 + 排名
在 PostgreSQL 中,一条 SQL 就能解决:
sql
SELECT
user_id,
COUNT(*) AS cnt,
RANK() OVER (ORDER BY COUNT(*) DESC) AS rank
FROM user_logs
GROUP BY user_id;
而在 MySQL 中(尤其是 8.0 之前):
- 要么拆成多条 SQL
- 要么在业务代码中排序、计算排名
👉 PostgreSQL 把复杂逻辑留在数据库层,代码明显更干净。
四、JSON 数据:压倒性的迁移理由
后来系统里出现了大量 半结构化数据:
- 用户配置
- 动态属性
- 扩展字段
一开始在 MySQL 中用 JSON 字段,但很快发现问题:
- 索引能力有限
- 查询性能不稳定
- 复杂 JSON 查询写起来很痛苦
而 PostgreSQL 的 JSONB:
- 原生支持索引(GIN)
- 查询语法清晰
- 可以直接对 JSON 字段做过滤、排序
sql
SELECT *
FROM users
WHERE profile->>'city' = 'Beijing';
👉 这一步之后,我基本确定要迁移了。
五、事务与一致性:心理负担明显变小
在订单、资金相关逻辑中,我越来越在意两点:
- 并发一致性
- 事务隔离级别是否"真有效"
PostgreSQL 的特点是:
- 真正的 MVCC
- 读写互不阻塞
SERIALIZABLE可用性高
迁移之后:
- 对"幻读""并发写覆盖"的担心明显减少
- 很多地方不用再手写锁逻辑
👉 数据库在帮我兜底,而不是我替数据库兜底。
六、索引与优化:PostgreSQL 更灵活
PostgreSQL 支持的索引类型非常丰富:
- 表达式索引
- 部分索引
- GIN / GiST / BRIN
例如直接对 JSON 字段建索引:
sql
CREATE INDEX idx_city
ON users ((profile->>'city'));
在 MySQL 中,这类需求往往只能靠冗余字段解决。
👉 PostgreSQL 给我的感觉是:
"你怎么查,我就怎么帮你优化。"
七、迁移后的真实感受
迁移完成后,并没有出现我最担心的问题:
❌ 性能明显下降
❌ 运维复杂到失控
反而出现了这些变化:
- SQL 数量变少
- 业务代码更简单
- 报表类功能开发速度明显提升
- 很多逻辑不再需要写在代码里
当然,PostgreSQL 也有代价:
- 学习成本更高
- DBA 思维要求更强
- 不适合"无脑 ORM"
八、我对 MySQL 和 PostgreSQL 的最终看法
MySQL 没有错,它只是更适合"简单明确的业务"。
而 PostgreSQL 更适合:
- 业务复杂
- 查询多变
- 强一致性要求
- 希望数据库承担更多计算能力的系统
我的结论是:
当你开始频繁吐槽 SQL 写得太难看、逻辑不得不放到代码里时,
PostgreSQL 很可能就是下一步。
九、写在最后
数据库选型,本质不是技术信仰,而是 业务匹配度。
我并不后悔用 MySQL 起步,
但也庆幸在合适的时间,选择了 PostgreSQL。