本内容是对知名性能评测博主 Anton Putra MySQL vs PostgreSQL Performance Benchmark (Latency - Throughput - Saturation) 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准
MySQL vs PostgreSQL 数据库性能对比**
在本内容中,我们将对比 MySQL 和 PostgreSQL 关系型数据库的性能。我们将运行一系列测试,其中 第一项测试 重点关注 数据写入(ingestion)效率。
首先,我们会测量:
- 数据插入请求的延迟,使用 p99 百分位数 进行评估
- 数据库的吞吐量,即每秒可处理的 请求数和插入数
- 数据库的饱和度(saturation),即数据库的负载情况,在这里我们主要关注:
- CPU 使用率
- 内存使用率
此外,我们还会测量:
- 磁盘写入操作数
- 数据库在磁盘上的存储效率
值得一提的是,这两种数据库在这些方面的差异 非常大。
最后,我们将评估 数据库的连接池(connection pool),观察它们如何管理插入数据的连接。
在 第二项测试 中,我们将测量 数据读取(retrieval) 的效率。
我使用的是当前最新版本:
- PostgreSQL 17.0
- MySQL 9.0
测试设计
为了进行测试,我在 两个数据库 中分别创建了 两张表,具体的 SQL 语句如下。
假设我们有一个 分析系统(analytics backend),用于记录 用户在网站上的行为,例如:
- 登录
- 登出
- 搜索
- 将商品加入购物车
数据库中有两张表:
- Customer 表
- 存储用户的 姓名、地址
- 设有 主键 ID
- Event 表
- 设有 主键 ID
- 外键 指向 Customer 表的主键
- 记录 用户执行的操作类型(action type)
第一项测试:
我们将使用以下 SQL 语句插入数据,随机生成客户 ID 和操作类型。
第二项测试:
我们将在包含 约 7000 万条记录 的数据库上执行 简单的 JOIN 查询:
- 随机生成一个 event ID
- 查询并连接 customer 表
- 返回用户的姓名、地址和操作类型
如果你有任何关于 改进测试设计 的建议,请告诉我!
代码概览
在客户端编写方面,我选择使用 Golang,因为:
- Golang 是一门流行的编程语言
- 它拥有成熟的数据库驱动库
为了让 MySQL 和 PostgreSQL 的测试尽可能公平,我使用 database/sql 接口 进行数据库操作,而不是直接使用 pgx 驱动(尽管 pgx 可能会降低查询延迟)。
但本次测试的重点是 对比数据库本身的性能,而不是不同的驱动实现。
此外,我确保:
- 执行相同的 SQL 查询
- 使用相同的数据库连接配置
如果你有任何改进建议,请告诉我,或者更好的是,提交一个 Pull Request!
第一项测试:数据写入
现在,我们开始 第一项测试。
这次测试 总共持续了近 3 小时,但我会将其压缩至 几分钟 展示。
测试过程中,我们会:
- 部署多个客户端
- 逐步增加负载
- 持续向数据库发送请求
- 每 60 秒增加一个虚拟客户端
你可以在 右上方的图表 看到 每秒查询数(QPS),而 左侧图表 显示的是 从客户端测量的插入延迟。
测试结果:
- 从一开始,PostgreSQL 的插入延迟明显低于 MySQL
- MySQL 插入数据的时间几乎是 PostgreSQL 的两倍
- PostgreSQL 的 CPU 使用率更低,意味着它有更大的吞吐能力
- PostgreSQL 占用的内存也更少
最大区别:
- MySQL 需要更多的磁盘操作来存储相同数量的记录
- PostgreSQL 在磁盘上的存储效率更高
- PostgreSQL 执行的磁盘操作更少,数据占用空间也更小
连接池情况:
- 两个数据库的连接池最终都达到了 80 个连接
- 每个客户端的最大连接数设置为 40
- 每个数据库有 2 个客户端在不断生成负载
临界点:
- 当 QPS 达到 5,500 时,MySQL 开始跟不上 PostgreSQL
- MySQL 的延迟和 CPU 使用率激增,导致整体性能下降
- 当 QPS 达到 12,000 时,我为 PostgreSQL 额外添加了一个客户端
- 最终,PostgreSQL 最高可处理 19,000 QPS(4 核 CPU + 直连 SSD)
- MySQL 最高只能处理 10,000 QPS,约为 PostgreSQL 的一半
第一项测试:数据分析
现在,我们查看 整个测试期间的数据:
- 每秒查询数(QPS)
- 插入延迟(客户端测量)
- CPU 使用率
- 总插入记录数
- PostgreSQL 插入 约 6500 万条记录
- MySQL 插入 约 5000 万条记录
- 在第二项测试前,我会为 MySQL 增加一些记录,使数据量一致
- 内存使用
- 磁盘写入操作
- 连接池大小
- 数据库大小
- PostgreSQL 存储数据的 磁盘效率更高
- CPU 和磁盘操作占用更少
- PostgreSQL 在数据写入方面明显优于 MySQL
第二项测试:数据读取
在运行 第二项测试 之前,我为 MySQL 额外添加了一些记录,使其与 PostgreSQL 的数据量保持一致。
测试内容:
- 查询 event 表中的数据
- 通过 event ID 进行 JOIN
- 返回用户的姓名、地址和操作类型
- 测试前,重启两个数据库,以清除缓存
磁盘读取数据问题:
- 由于可能的配置错误,我没有获取到 PostgreSQL 的磁盘读取数据
- 但我仍然有 MySQL 的磁盘操作数据
测试结果:
- 延迟差距不像第一项测试那么大
- 但 PostgreSQL 仍然比 MySQL 低延迟
- MySQL 的 CPU 使用率 显著高于 PostgreSQL
- 这个趋势一直持续,直到 MySQL 达到 CPU 使用瓶颈,性能下降
临界点:
- 当 QPS 达到 18,000 时,MySQL 的性能下降更明显
- MySQL 的延迟出现波动,而 PostgreSQL 仍然保持稳定
- 当 QPS 达到 20,000 时,MySQL 无法再处理更多查询
- 我为 PostgreSQL 额外增加了一个客户端,加速测试
- 最终,PostgreSQL 在 32,000 QPS 时达到 90% CPU 使用率,开始下降
结论:
- 在数据写入和读取方面,PostgreSQL 都比 MySQL 更高效
- 如果你有任何改进建议,例如更改客户端代码或测试设计,请告诉我!
第二项测试:数据分析
现在,我们查看 整个测试期间的数据:
- 每秒查询数(QPS)
- 数据读取延迟
- CPU 使用率
- 内存使用
- 数据库连接数
- 磁盘读取操作