Py学习  »  DATABASE

PostgreSQL 已经很强,为什么还要使用MySQL?

鸭哥聊Java • 1 月前 • 69 次点击  

线上接口突然慢下来,第一眼看日志,数据库耗时只写着一行:

SQL cost=842ms, datasource=order-db, sql=select * from order_item where order_id = ?

这种日志我一般不会马上骂 MySQL,也不会马上吹 PostgreSQL。先看执行计划,再看连接池,再看团队是不是把一个简单查询写成了“数据库能力秀”。

面试里问:PostgreSQL 已经很强,为什么还要用 MySQL?

这个问题要是回答“因为 MySQL 简单、生态好”,只能算答到门口。真到项目里选型,数据库不是谁功能多谁赢,是谁更适合这套系统、这帮人、这堆历史包袱。

PostgreSQL 强,这个没什么好争的。

它的 SQL 标准支持更完整,复杂查询、窗口函数、CTE、JSON、数组、GIS 这些能力都很舒服。复杂报表、多维查询、偏分析的业务,用 PostgreSQL 经常能少绕很多弯子。很多场景下,PostgreSQL 的执行器、类型系统、扩展能力确实更像一个“数据库平台”。

但问题来了,业务系统不全是复杂查询。

大量 Java 后台系统,核心 SQL 长这样:

select idstatus, pay_amount
from t_order
where user_id = ?
  and create_time >= ?
order by id desc
limit 20;

再复杂一点,也就是:

update t_order
set status = ?, pay_time = now()
where order_no = ?
  and status = 'WAIT_PAY';

这种 OLTP 场景,真正拼的不是数据库有没有高级类型,而是稳定、可预期、好排查、团队都能接住。

MySQL 的优势就在这里。

Java 生态里,MySQL 太常见了。Spring Boot、MyBatis、JPA、ShardingSphere、Canal、Debezium、各类 Druid/Hikari 监控,默认文档里十有八九先拿 MySQL 举例。出了问题,搜索报错、查执行计划、看慢 SQL、问 DBA,路径都很短。

比如慢 SQL 排查,MySQL 这套东西大家太熟了:

explain
select  idstatus
from t_order
where user_id = 10086
order by create_time desc
limit 10;

看到 type=rangekey=idx_user_timerows=30,基本心里有数。

要是看到这个:

type=ALL
key=NULL
rows=780000
Extra=Using where; Using filesort

不用开会,先补索引:

create index idx_order_user_time
on t_order(user_id, create_time);

PostgreSQL 当然也能看执行计划,而且信息更多。但说实话,信息多不等于团队能用好。线上出故障的时候,不是比谁理论懂得多,是比谁能在十分钟内把问题收住。

还有一个很现实的点:历史系统。

很多公司不是今天从零开始选数据库。它可能十年前就用了 MySQL,表结构、分库分表、binlog 同步、数据订正脚本、运维备份、监控告警,全都围着 MySQL 长出来了。

你说 PostgreSQL 更强,没错。

但把一个跑了多年的订单库迁过去,不是改个 JDBC URL:

spring:
  datasource:
    url: jdbc:mysql://mysql-prod:3306/trade
    username: app_trade

换成:

spring:
  datasource:
    url: jdbc:postgresql://pg-prod:5432/trade

就完事了?

别闹。

字段类型要核,SQL 方言要改,自增主键要处理,分页语法要扫,时间类型要测,事务隔离差异要压,线上回滚方案还得准备。尤其 Java 项目里那些散落在 XML 里的动态 SQL,平时看着安静,一迁库全出来咬人。

我见过最烦的一类 SQL,不是多复杂,而是这种:

<select id="listByIds" resultType="OrderDO">
    select *
    from t_order
    where id in
    <foreach collection="ids" item="id" open="(" separator="," close=")">
        #{id}
    foreach>
select>

这种在 MySQL 跑了很多年,大家默认没问题。迁库时一旦涉及批量大小、参数绑定、执行计划变化,就得重新测。数据库迁移最怕的不是“不能跑”,是“能跑,但偶尔慢”。

MySQL 还有一个非常实用的能力:主从复制和 binlog 生态。

很多 Java 系统做缓存更新、搜索同步、数据异构,都是靠 binlog 往外推。比如订单表变更后,同步到 ES:

MySQL binlog -> Canal -> MQ -> search-service -> Elasticsearch

这条链路太成熟了。出了问题也好查:

show master status;
show slave status\G;

延迟、位点、relay log、GTID,DBA 和后端都知道该看哪里。PostgreSQL 也有逻辑复制,也能做 CDC,但在不少团队里,MySQL 这套链路的熟练度就是更高。

选型的时候,我会把问题拆得更粗暴一点。

如果是交易、订单、账户、库存这种典型 OLTP,SQL 不复杂,写多读多,团队 MySQL 经验足,周边组件也都是 MySQL 生态,那我倾向 MySQL。

不是因为它更高级,而是因为它够用,且风险小。

如果是复杂权限查询、报表分析、地理位置、JSON 结构很多、需要更强 SQL 表达能力,或者项目本来就有 PostgreSQL DBA,那 PostgreSQL 很香。

但别拿 PostgreSQL 的强项去打 MySQL 的日常场景。

面试时可以这样答:

PostgreSQL 很强,但数据库选型不是单看功能上限。MySQL 在 Java Web 和互联网 OLTP 场景里生态更成熟,团队经验更普遍,运维、监控、分库分表、binlog 同步、故障排查链路都更短。大量业务只是简单增删改查,MySQL 的能力已经够用,而且稳定、成本低、迁移风险小。PostgreSQL 更适合复杂 SQL、扩展能力要求高、数据类型丰富的场景;MySQL 更适合团队协作成本敏感、链路成熟度要求高的常规业务系统。

最后补一句我自己的判断。

技术选型不要只看“谁更强”,要看“谁出事的时候你能不能救回来”。

线上凌晨两点,慢 SQL 打满连接池,业务还在催单。这个时候你最需要的,不是数据库功能表上多几个勾,而是团队有人能立刻看懂这条日志:

HikariPool-1 - Connection is not available, request timed out after 30000ms

然后知道下一步该查慢 SQL、查连接池、查锁等待,还是查主从延迟。

能救火的技术,才是真的适合生产。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/196684