MySQL与PostgreSQL性能对比测试 包含吞吐量和延迟,读和写

AI 智能摘要
MySQL(海豚)和 PostgreSQL(大象)都是最好的、最广泛使用的开源数据库之一。它们经常从多个角度进行比较:支持的功能、SQL方言差异、架构和内部、资源利用率以及 - 性能。很多小伙伴接触到这两个数据库,不知道那个数据库比较好?主题铺看到一篇文章,转过来,分享一下MySQL与PostgreSQL性能:吞吐量和延迟,读和写的全面对比。
图片[1]-MySQL与PostgreSQL性能对比测试 包含吞吐量和延迟,读和写-主题铺

MySQL(海豚)和 PostgreSQL(大象)都是最好的、最广泛使用的开源数据库之一。它们经常从多个角度进行比较:支持的功能、SQL方言差异、架构和内部、资源利用率以及 – 性能。很多小伙伴接触到这两个数据库,不知道那个数据库比较好?主题铺看到一篇文章,转过来,分享一下MySQL与PostgreSQL性能:吞吐量和延迟,读和写的全面对比。

今天,我们将尽可能深入、广泛地研究性能 – 运行许多(17)个测试用例,并使用各种查询和工作负载,使用几张表来模拟现实世界中最常见场景,衡量吞吐量和延迟。然后让我们开始寻找答案:

哪个数据库,MySQL 或 PostgreSQL,性能更好?

配置

整个测试配置可以在 GitHub 仓库中找到。

正如 我们所知 ,MySQL 和 PostgreSQL 在实现选择上有很大差异 ;为了捕捉这些差异,有几个表(PostgreSQL 定义):

CREATE TABLE "user" (
  id BIGSERIAL PRIMARY KEY,
  email VARCHAR(255) UNIQUE NOT NULL,
  created_at TIMESTAMP NOT NULL,
  updated_at TIMESTAMP
);

CREATE TABLE "order" (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
  created_at TIMESTAMP NOT NULL,
  updated_at TIMESTAMP
);
CREATE INDEX order_user_id ON "order"(user_id);

CREATE TABLE "item" (
  id BIGSERIAL PRIMARY KEY,
  name VARCHAR(255) NOT NULL UNIQUE,
  description TEXT,
  price NUMERIC(10, 2) NOT NULL,
  created_at TIMESTAMP NOT NULL,
  updated_at TIMESTAMP
);

CREATE TABLE "order_item" (
  id BIGSERIAL PRIMARY KEY,
  order_id BIGINT NOT NULL REFERENCES "order"(id) ON DELETE CASCADE,
  item_id BIGINT NOT NULL REFERENCES "item"(id) ON DELETE CASCADE
);
CREATE INDEX order_item_order_id ON "order_item"(order_id);
CREATE INDEX order_item_item_id ON "order_item"(item_id);

为了使结果可重复并更好地控制资源利用率,这两个数据库和测试都在 Docker 中运行。MySQL,版本 9.5,具有以下配置:

docker run -d -v "${volume_dir}:/var/lib/mysql" --network host \
  -e "MYSQL_ROOT_PASSWORD=performance" \
  -e "MYSQL_DATABASE=performance" \
  --memory "16G" --cpus "8" --shm-size="1G" \
  --name $container_name $container_name \
  --innodb_buffer_pool_size=12G \
  --innodb_redo_log_capacity=2G \
  --transaction-isolation='READ-COMMITTED'

一些重要的自定义设置:

  • 内存和 CPU – 分别限制在 16G 和 8 个;共享内存也从悲剧性的 64MB 默认值增加了
  • innodb_buffer_pool_size – 增加了用于数据索引缓存的总内存,以减少 I/O 并提高性能
  • innodb_redo_log_capacity – 增加了重做日志文件占用的磁盘空间,以改善写入性能;某些写入操作发生的频率降低了
  • 读已提交事务隔离 – MySQL 的默认值是 可重复读 ;将其设置为与 PostgreSQL 默认值(读已提交)相同的(较低的)值可以使比较更公平,因为更高的隔离级别会引入额外的性能开销

PostgreSQL,版本 18.1,具有以下配置:

docker run -d -v "${volume_dir}:/var/lib/postgresql" --network host \
  -e "POSTGRES_PASSWORD=performance" \
  -e "POSTGRES_DB=performance" \
  --memory "16G" --cpus "8" --shm-size="1G" \
  --name $container_name $container_name \
  -c shared_buffers=4GB \
  -c work_mem=64MB \
  -c effective_cache_size=12GB

同样,一些重要的调整:

  • shared_buffers – 与 MySQL 的 innodb_buffer_pool_size 非常相似;略小一些,因为 PostgreSQL 会大量使用操作系统的页缓存
  • work_mem – 增加用于内部排序操作和哈希表的最大内存使用量(每个查询操作),这些内部用于某些连接和聚合
  • effective_cache_size – 增加查询规划器用于估计可用于缓存数据的总内存量的参数

这些自定义化的目标不是拥有绝对最佳的配置,而是稍微优化数据库;充分利用其性能,而不是追求最后那几个百分点的性能。

然后,还有用于运行测试的 SqlDbPerformanceTests.java 测试程序——在两个数据库上执行各种测试并输出详细统计数据。为了简化管理,它也是构建在 Docker 中运行的(Java 25 & Maven)。通过简单的 run_test.py Python 脚本,可以更轻松地配置它并从多个可用的测试用例(17 个)中选择。

由于数据库有 8 个 CPU 可用 ,连接池大小为:8 * 16 = 128(MySQL)和 8 * 8 = 64(PostgreSQL)。实际测试表明,MySQL 受益于更多的连接,从而获得更好的性能;尤其是在写密集型工作负载中。

测试用例设计为运行几个回合 – 每秒执行 QUERIES_RATE 个,总共执行配置的 QUERIES_TO_EXECUTE 个。根据具体场景,这些数字从每秒几百个到几万个不等;大多数情况下为 QUERIES_TO_EXECUTE = 10 * QUERIES_RATE 。

要运行测试(本地),有几个脚本可以启动 Docker 中的 MySQL 和 PostgreSQL 实例,并在 Docker 中构建和运行 SqlDbPerformanceTests.java,选择测试用例和数据库。这一切都归结于执行:

# builds and runs MySQL in Docker
./build_and_run_mysql.bash

# builds and runs PostgreSQL in Docker
./build_and_run_postgresql.bash

# builds, without running just yet, performance tests in Docker
./build_performance_tests.bash

# runs performance tests in Docker, with the chosen test case & DB
./run_test.py

环境

所有测试将在我的本地计算机上运行:

  • CPU – AMD Ryzen 7 PRO 7840U;8 个核心和 16 个线程,基础时钟速度为 3.3 GHz,最高加速至 5.1 GHz
  • 内存 – 32 GiB
  • 操作系统 – Ubuntu 24.04.3 LTS

磁盘(1 TB)详情:

sudo lshw -class disk -class storage

description: NVMe device
product: SAMSUNG MZVL21T0HDLU-00BLL
vendor: Samsung Electronics Co Ltd
bus info: pci@0000:03:00.0
version: 6L2QGXD7
width: 64 bits
clock: 33MHz
capabilities: nvme pm msi pciexpress msix nvm_express bus_master cap_list
configuration: driver=nvme latency=0 nqn=nqn.1994-11.com.samsung:nvme:PM9A1a:M.2:S75YNF0XC05149 state=live
resources: irq:68 memory:78c00000-78c03fff

如前所述,数据库在 Docker 中运行,内存限制为 16G,CPU 为 8 个。测试运行器没有任何限制。

结果

所有测试结果也都可以在 GitHub 仓库中找到。

我们开始时,两个数据库都在 Docker 中运行,并且是空的——只有表架构被初始化。在结果中,我们将看到:

Total test duration: PT14.471S
Queries duration: PT10.619S

这些时间有时可能会有很大差异——这是因为对于某些测试用例,需要从数据库中获取现有数据以构建测试查询。这些额外查询的持续时间会从总测试持续时间中扣除: Queries duration = Total test duration - Additional queries duration 。否则,它们会扭曲结果,在不应计算时间的地方增加了时间。

正如所说,我们将运行大量案例,测试各种查询和工作负载。在执行 python3 run_test.py 时,以下选项可用:

  1. 插入用户
  2. 批量插入项目
  3. 批量插入订单
  4. 批量插入订单项
  5. SELECT USERS BY ID
  6. SELECT USERS BY EMAIL
  7. SELECT 排序按 ID 用户页面
  8. SELECT 订单 JOINED WITH 用户
  9. SELECT 订单 JOINED WITH 商品
  10. SELECT 用户 WITH 订单统计按 ID
  11. 根据 ID 更新用户邮箱
  12. 更新用户,通过 ID 更新 ATS
  13. 更新 ID 以多列方式更新用户
  14. 按 ID 删除订单
  15. 按 ID 批量删除订单
  16. 在事务中插入用户和订单及项目
  17. 按 ID 插入、更新、删除和选择用户

运行前 4 个插入选项后,每个数据库都将存储:

  • 500 000 用户
  • 500 000 项目
  • 2 000 000 个订单
  • 4 000 000 个订单项关联

用于接下来的选择、更新、删除和混合测试用例。

插入

插入用户 – 插入 500 000 个用户,期望 10 000 QPS(每秒查询次数)的速率,逐个插入:

MySQL | PostgreSQL

Total test duration: PT1M54.078S | PT51.742S
Queries duration: PT1M54.078S | PT51.742S

Executed queries: 500000

Wanted queries rate: 10000/s
Actual queries rate: 4383/s | 9663/s

Min: 7.362 ms | 1.041 ms
Max: 150.018 ms | 40.748 ms
Mean: 26.801 ms | 2.191 ms

Percentile 50 (Median): 26.498 ms | 2.158 ms
Percentile 90: 31.082 ms | 2.658 ms
Percentile 99: 42.729 ms | 3.84 ms
Percentile 99.9: 114.339 ms | 13.304 ms

PostgreSQL 在这方面表现要好得多,而且我们可以清楚地看到——这个负载对 MySQL(海豚)来说已经太大了,而大象似乎仍然轻松呼吸,所以让我们用 30 000 QPS 重新运行它:

PostgreSQL

Total test duration: PT23.432S
Queries duration: PT23.432S

Executed queries: 500000

Wanted queries rate: 30000/s
Actual queries rate: 21338/s

Min: 1.159 ms
Max: 37.963 ms
Mean: 2.386 ms

Percentile 50 (Median): 2.367 ms
Percentile 90: 2.578 ms
Percentile 99: 4.009 ms
Percentile 99.9: 12.218 ms

21 338 次/秒的插入量,与 MySQL 的 仅 4383 次/秒相比 – Postgres 性能令人印象深刻,吞吐量赢了 4.87 倍!

批量插入项目 – 批量插入 500 000 项,每批 100 项,目标为 500 QPS

MySQL | PostgreSQL

Total test duration: PT24.958S | PT23.651S
Queries duration: PT24.958S | PT23.651S

Executed queries: 5000

Wanted queries rate: 500/s
Actual queries rate: 200/s | 211/s

Min: 11.156 ms | 2.424 ms
Max: 232.688 ms | 36.817 ms
Mean: 26.504 ms | 4.1 ms

Percentile 50 (Median): 25.89 ms | 3.909 ms
Percentile 90: 35.57 ms | 5.113 ms
Percentile 99: 45.759 ms | 6.88 ms
Percentile 99.9: 183.714 ms | 30.237 ms

对于这两个数据库来说都稍微有点多;在吞吐量方面,差异并不大 – 200 QPS 对比 211 QPS,每个查询插入 100 项 。另一方面,Postgres 的延迟(查询持续时间)明显更低(更好)- 平均值 4.1 毫秒 对比 26.504 毫秒 ,99 分位数 6.88 毫秒 对比 45.759 毫秒 

批量插入订单 – 批量插入 2 000 000 个订单,每批 100 个,目标为 2000 QPS

MySQL | PostgreSQL 

Total test duration: PT14.471S | PT11.004S
Queries duration: PT10.619S | PT6.759S 

Executed queries: 20000

Wanted queries rate: 2000/s 
Actual queries rate: 1883/s | 2959/s

Min: 12.355 ms | 2.026 ms 
Max: 268.408 ms | 53.068 ms
Mean: 51.606 ms | 13.786 ms

Percentile 50 (Median): 45.796 ms | 13.701 ms 
Percentile 90: 76.863 ms | 21.716 ms
Percentile 99: 146.497 ms | 38.114 ms
Percentile 99.9: 172.807 ms | 49.143 ms

大象明显超出了预期,在这里,无论是在吞吐量还是延迟方面,都优于海豚。让我们用 4000 QPS 重复一遍:

PostgreSQL

Total test duration: PT10.173S
Queries duration: PT5.658S

Executed queries: 20000

Wanted queries rate: 4000/s
Actual queries rate: 3535/s

Min: 2.487 ms
Max: 90.238 ms
Mean: 14.697 ms

Percentile 50 (Median): 13.997 ms
Percentile 90: 22.082 ms
Percentile 99: 34.779 ms
Percentile 99.9: 75.629 ms

因此,PostgreSQL 的 3535 次/秒插入 100 条记录 ,而 MySQL 的 1883 次/秒插入 

批量插入订单项 – 通过将记录插入到 order_item 表中,将现有订单与现有项目关联起来。以 1000 为批次插入 4 000 000 行,实现所需的 400 QPS

MySQL | PostgreSQL

Total test duration: PT41.329S | PT23.654S
Queries duration: PT7.365S | PT10.271S

Executed queries: 4000

Wanted queries rate: 400/s
Actual queries rate: 543/s | 389/s

Min: 25.842 ms | 32.322 ms
Max: 505.263 ms| 447.523 ms
Mean: 247.138 ms | 192.304 ms

Percentile 50 (Median): 221.993 ms | 188.728 ms
Percentile 90: 403.34 ms | 288.398 ms
Percentile 99: 482.361 ms | 394.913 ms
Percentile 99.9: 504.069 ms | 430.7 ms

令人惊讶的是,首条插入在吞吐量方面获胜的是海豚——543 QPS 对 389 QPS,性能提升 1.4 倍 。延迟实际上对大象来说更低(更好),所以总体而言,这基本上是平局。

总体来看插入操作,除了一个案例外,PostgreSQL 在吞吐量和延迟方面都占优。

选择

按 ID 选择用户 – 以所需的 50 000 QPS 速率按 ID 选择用户:

MySQL | PostgreSQL

Total test duration: PT16.428S | PT11.935S
Queries duration: PT14.939S | PT11.282S

Executed queries: 500000

Wanted queries rate: 50000/s
Actual queries rate: 33469/s | 44315/s

Min: 0.09 ms | 0.08 ms
Max: 100.489 ms | 101.967 ms
Mean: 1.579 ms | 0.523 ms

Percentile 50 (Median): 1.064 ms | 0.359 ms
Percentile 90: 2.665 ms | 0.921 ms
Percentile 99: 12.721 ms | 2.59 ms
Percentile 99.9: 25.143 ms | 14.47 m

大象似乎还有一些余力;使用 75 000 QPS 重新运行它:

PostgreSQL

Total test duration: PT11.264S
Queries duration: PT9.058S

Executed queries: 500000

Wanted queries rate: 75000/s
Actual queries rate: 55200/s

Min: 0.084 ms
Max: 102.201 ms
Mean: 0.874 ms

Percentile 50 (Median): 0.653 ms
Percentile 90: 1.348 ms
Percentile 99: 5.446 ms
Percentile 99.9: 18.749 m

PostgreSQL 击败了 MySQL;优势在单次插入上不如明显,但仍然很大 – 55,200 QPS 对比 33,469 QPS;平均值为 0.874 毫秒 对比 1.579 毫秒 ,以及 5.446 毫秒 对比 12.721 毫秒 在 99 分位数上。

按邮箱查询用户 – 通过邮箱( 辅助索引 )读取用户,目标为 50 000 QPS

MySQL | PostgreSQL

Total test duration: PT17.139S | PT12.047S
Queries duration: PT15.631S | PT11.280S

Executed queries: 500000

Wanted queries rate: 50000/s
Actual queries rate: 31988/s | 44324/s

Min: 0.106 ms | 0.086 ms
Max: 99.775 ms | 59.287 ms
Mean: 1.772 ms | 0.612 ms

Percentile 50 (Median): 1.234 ms | 0.447 ms
Percentile 90: 2.985 ms | 1.088 ms
Percentile 99: 12.865 ms | 2.812 ms
Percentile 99.9: 26.701 ms | 11.028 ms

大象已经获胜,但仍能轻松呼吸——让我们同样以 75 000 QPS 的目标再次运行此案例:

PostgreSQL

Total test duration: PT10.862S
Queries duration: PT9.348S

Executed queries: 500000

Wanted queries rate: 75000/s
Actual queries rate: 53487/s

Min: 0.084 ms
Max: 82.551 ms
Mean: 0.834 ms

Percentile 50 (Median): 0.618 ms
Percentile 90: 1.288 ms
Percentile 99: 5.358 ms
Percentile 99.9: 16.843 ms

对 PostgreSQL 来说更是大胜 – 53,487 QPS 对比 31,988 QPS;延迟也更低。

按 ID 排序选择用户页面 – 目标为 5000 QPS,按 ID 升序选择用户;结果限制为从 10 到 100 的随机数,偏移量也是随机的,范围在 0 到 10 000 之间:

MySQL | PostgreSQL

Total test duration: PT10.968S | PT10.537S
Queries duration: PT10.968S | T10.537S

Executed queries: 50000

Wanted queries rate: 5000/s
Actual queries rate: 4559/s | 4745/s

Min: 0.139 ms | 0.118 ms
Max: 71.472 ms | 51.453 ms
Mean: 3.118 ms | 1.556 ms

Percentile 50 (Median): 1.561 ms | 1.117 ms
Percentile 90: 6.297 ms | 2.362 ms
Percentile 99: 41.294 ms | 9.146 ms
Percentile 99.9: 55.248 ms | 42.884 m

有趣的是,在吞吐量方面,DBs 非常接近的第一个 select 案例是 4559 QPS 对比 4745 QPS。但总体而言,Postgres 仍然占据优势。

现在,我们将介绍一些连接操作。

选择与用户连接的订单 – 以想要的 35 000 QPS 速率读取订单 ID,并将它们与用户通过 o.user_id = u.id 进行连接。订单和用户之间存在多对一的关系:

MySQL | PostgreSQL

Total test duration: PT14S | PT13.154S
Queries duration: PT11.977S | PT12.414S

Executed queries: 350000

Wanted queries rate: 35000/s
Actual queries rate: 29223/s | 28194/s

Min: 0.105 ms | 0.152 ms
Max: 99.931 ms | 54.302 ms
Mean: 1.739 ms | 1.897 ms

Percentile 50 (Median):  1.177 ms | 1.321 ms
Percentile 90: 2.923 ms | 2.85 ms
Percentile 99: 14.543 ms | 19.823 ms
Percentile 99.9: 27.36 ms | 26.859 ms

最后,MySQL 击败了 Postgres,尽管只是略微 – 29 223 QPS 对比 28 194 QPS;延迟也大多是较低的。

SELECT ORDERS JOINED WITH ITEMS – 以每秒 30,000 个查询(30 000 QPS)的速率按 id 读取订单,首先通过 order_item.order_id 将订单与订单项进行连接,然后通过 order_item.item_id 将订单项与商品进行连接。订单与订单项之间存在多对多的关系;订单项与商品之间也存在相同类型的关系。此案例测试了双方都具有多对多关系的双重连接。

MySQL | PostgreSQL

Total test duration: PT14.859S | PT15.566S
Queries duration: PT13.263S | PT14.843S

Executed queries: 300000

Wanted queries rate: 30000/s
Actual queries rate: 22619/s | 20211/s

Min: 0.155 ms | 0.199 ms
Max: 77.021 ms | 80.307 ms
Mean: 2.824 ms | 2.799 ms

Percentile 50 (Median): 1.962 ms | 1.866 ms
Percentile 75: 3.219 ms | 2.748 ms
Percentile 90: 5.091 ms | 4.093 ms
Percentile 99: 19.795 ms | 28.604 ms
Percentile 99.9: 29.203 ms | 34.309 ms

Dolphin 再次获胜!它似乎确实在连接方面表现更好;吞吐量 比之前提高了 1.12 倍 – 22,619 QPS 对比 20,211 QPS,而延迟则表现不一;部分情况有所改善 – 更高的百分位数,部分情况则有所恶化 – 更低的百分位数和平均值。

按 ID 选择具有订单统计的用户 – 通过 id 选择用户,将其与订单进行 u.id = o.user_id (一对多) 的连接,并为每个用户计算各种统计数据:COUNT(*) AS orders、 MIN(o.created_at) AS oldest_order_created_at 和 MAX(o.created_at) AS latest_order_created_at 。目标速率是 40 000 QPS

MySQL | PostgreSQL

Total test duration: PT18.485S | PT13.101S
Queries duration: PT17.505S | PT12.621S

Executed queries: 400000

Wanted queries rate: 40000/s
Actual queries rate: 22851/s | 31693/s

Min: 0.151 ms | 0.138 ms
Max: 106.217 ms | 113.18 ms
Mean: 2.759 ms | 1.648 ms

Percentile 50 (Median): 1.77 ms | 1.137 ms
Percentile 90: 5.092 ms | 2.622 ms
Percentile 99: 19.511 ms | 15.651 ms
Percentile 99.9: 34.338 ms | 23.988 ms

出乎意料的是,在最后一个连接案例中,大象具有优势——31,693 QPS 对比 22,851 QPS,性能提升 1.39 倍;延迟也更低。

总结选择查询:

  • Postgres 在单表单行选择上表现优异
  • 对于单表多行排序选择,两个数据库的性能非常接近
  • MySQL 在连接方面略有优势
  • 使用聚合函数的查询对 Elephant 来说性能更优

更新

通过 ID 更新用户邮箱 – 通过 id 更新用户邮箱(索引列),以期望的 5000 QPS 的速率:

MySQL | PostgreSQL

Total test duration: PT13.612S | PT10.245S
Queries duration: PT13.29S | PT10.108S

Executed queries: 50000

Wanted queries rate: 5000/s
Actual queries rate: 3762/s | 4946/s

Min: 6.71 ms | 1.101 ms
Max: 61.503 ms | 16.098 ms
Mean: 26.337 ms | 2.506 ms

Percentile 50 (Median): 26.457 ms | 2.423 ms
Percentile 90: 31.342 ms | 2.947 ms
Percentile 99: 36.415 ms | 9.243 ms
Percentile 99.9: 42.76 ms | 13.755 ms

对于 MySQL 已经太过于多了一——它峰值仅为 3762 QPS,未能达到 5000 QPS。大象似乎远低于其极限运行;让我们以 4 倍更高的速率重新运行此案例——20 000 QPS

PostgreSQL

Total test duration: PT11.608S
Queries duration: PT11.057S

Executed queries: 200000

Wanted queries rate: 20000/s
Actual queries rate: 18088/s

Min: 1.141 ms
Max: 17.132 ms
Mean: 2.483 ms

Percentile 50 (Median): 2.458 ms
Percentile 90: 2.897 ms
Percentile 99: 4.827 ms
Percentile 99.9: 10.896 ms

好吧,海豚在这里完全落后——3762 QPS 对比 18 088 QPS,差了 4.8 倍 ,与大象相比;延迟也更高。

UPDATE USER UPDATED ATS BY ID – 通过 ID 修改用户更新时间戳(未索引列),期望的速率 5000 QPS

MySQL | PostgreSQL

Total test duration: PT11.653S | PT10.239S
Queries duration:  PT11.344S | PT9.947S

Executed queries: 50000

Wanted queries rate: 5000/s
Actual queries rate: 4408/s | 5026/s

Min: 0.128 ms | 1.089 ms
Max: 114.719 ms | 12.321 ms
Mean: 15.172 ms | 2.351 ms

Percentile 50 (Median): 17.715 ms | 2.368 ms
Percentile 90: 33.223 ms | 2.891 ms
Percentile 99: 37.726 ms | 3.588 ms
Percentile 99.9: 110.402 ms | 8.559 ms

如前所述,大象(Elephant)再次表现出色,尽管优势不那么明显。但再次运行它,使用 20 000 QPS

PostgreSQL

Total test duration: PT11.588S
Queries duration: PT10.802S

Executed queries: 200000

Wanted queries rate: 20000/s
Actual queries rate: 18515/s

Min: 1.115 ms
Max: 16.476 ms
Mean: 2.524 ms

Percentile 50 (Median): 2.52 ms
Percentile 90: 2.966 ms
Percentile 99: 4.977 ms
Percentile 99.9: 11.745 ms

与邮件更新相比,海豚在这里完全处于劣势 – 4408 QPS 对比 18 515 QPS,差了 4.2 倍 ;延迟也更高。

最后,关于更新操作,我们有 通过 ID 更新用户多个列 – 通过 ID 更改用户的电子邮件(索引)和更新时间(非索引);同样地,对于 5000 QPS 的目标:

MySQL | PostgreSQL

Total test duration: PT13.722S | PT10.228S
Queries duration: PT13.345S | PT9.989S

Executed queries: 50000

Wanted queries rate: 5000/s
Actual queries rate: 3747/s | 5005/s

Min: 6.812 ms | 1.114 ms
Max: 117.566 ms | 14.903 ms
Mean: 26.284 ms | 2.387 ms

Percentile 50 (Median): 26.161 ms | 2.394 ms
Percentile 90: 31.188 ms | 2.906 ms
Percentile 99: 39.774 ms | 4.108 ms
Percentile 99.9: 113.642 ms | 9.15 m

PostgreSQL 再次优于 MySQL。既然大象似乎对这种负载不再感到印象深刻,这里提供的是 20 000 QPS 版本:

PostgreSQL

Total test duration: PT11.665S
Queries duration: PT11.083S

Executed queries: 200000

Wanted queries rate: 20000/s
Actual queries rate: 18046/s

Min: 1.088 ms
Max: 16.465 ms
Mean: 2.507 ms

Percentile 50 (Median): 2.463 ms
Percentile 90: 2.947 ms
Percentile 99: 4.704 ms
Percentile 99.9: 10.178 ms

18,046 QPS 对比 3,747 QPS – Postgres 占据优势 4.82 倍。

对于更新操作,象形符号在所有情况下都更优越。

删除操作

按 ID 删除订单 – 以所需的 10 000 QPS 速率删除订单。重要的是,订单与 order_item 表相关联(多对多);删除一个订单会级联到相关的订单项:

MySQL | PostgreSQL

Total test duration: PT19.589S | PT10.776S
Queries duration: PT17.871S | PT10.35S

Executed queries: 100000

Wanted queries rate: 10000/s
Actual queries rate: 5596/s | 9662/s

Min: 0.139 | 0.085 ms
Max: 119.909 ms | 16.123 ms
Mean: 20.563 ms | 1.953 ms

Percentile 50 (Median): 22.36 ms | 2.191 ms
Percentile 90: 31.335 ms | 2.628 ms
Percentile 99: 43.039 ms | 4.334 ms
Percentile 99.9: 114.248 ms | 13.747 ms

在更新操作方面,PostgreSQL 获胜,并且仍有提升空间;再次运行以 20 000 QPS 为目标的案例:

PostgreSQL

Total test duration: PT11.408S
Queries duration: PT10.938S

Executed queries: 200000

Wanted queries rate: 20000/s
Actual queries rate: 18285/s

Min: 0.084 ms
Max: 18.622 ms
Mean: 2.009 ms

Percentile 50 (Median): 2.285 ms
Percentile 90: 2.917 ms
Percentile 99: 4.661 ms
Percentile 99.9: 13.522 ms

18,285 QPS 与 5,596 QPS 的吞吐量对比,性能提升 3.27 倍;延迟也更低。

按 ID 批量删除订单 – 按批量删除订单,每批 100 个,目标 1000 QPS。如前所述,重要的是要记住订单与 order_item 表相关联;删除订单会级联到相关的订单项:

MySQL | PostgreSQL

Total test duration: PT32.555S | PT10.135S
Queries duration: PT16.125S | PT7.445S

Executed queries: 10000

Wanted queries rate: 1000/s
Actual queries rate: 620/s | 1343/s

Min: 16.219 ms | 1.572 ms
Max: 925.516 ms | 117.852 ms
Mean: 181.728 ms | 11.387 ms

Percentile 50 (Median): 144.041 ms | 4.975 ms
Percentile 90: 372.383 ms | 29.104 ms
Percentile 99: 670.586 ms | 60.834 ms
Percentile 99.9: 846.825 ms | 89.203 ms

为 PostgreSQL 提供更多展示其优势的空间,使用 20 000 QPS

PostgreSQL

Total test duration: PT11.184S
Queries duration: PT6.943S

Executed queries: 20000

Wanted queries rate: 2000/s
Actual queries rate: 2881/s

Min: 1.868 ms
Max: 143.329 ms
Mean: 16.547 ms

Percentile 50 (Median): 12.604 ms
Percentile 90: 34.174 ms
Percentile 99: 66.48 ms
Percentile 99.9: 102.943 ms

为大象带来了又一次完胜 – 2881 QPS 对比 620 QPS,性能提升 4.65 倍 

在更新操作方面,PostgreSQL 在删除操作上总体表现更优。

事务

在事务中插入用户、订单和订单项 – 在单个事务中插入一个用户和一个包含两个项目的订单。这需要 4 条插入语句:1 条用于 user 表,1 条用于 order 表,以及 2 条用于 order_item 表。目标是在每秒执行 2500 此类事务,这相当于 4 * 2500 = 10 000 QPS

MySQL | PostgreSQL

Total test duration: PT11.921S | PT10.104S
Queries duration: PT10.522S | PT9.742S

Executed queries: 25000

Wanted queries rate: 2500/s
Actual queries rate: 2376/s | 2566/s

Min: 10.33 ms | 1.289 ms
Max: 118.617 ms | 16.185 ms
Mean: 26.841 ms | 2.821 ms

Percentile 50 (Median): 25.505 ms | 2.672 ms
Percentile 90: 35.535 ms | 3.483 ms
Percentile 99: 62.132 ms | 6.525 ms
Percentile 99.9: 111.082 ms | 10.12 m

由于单次插入对海豚来说存在问题,因此大象在这里获胜并不令人意外:2566 QPS 对比 2376 QPS,延迟也更低。既然它们似乎还有余力,让我们用 4 * 5000 = 20 000 QPS 对 MySQL 进行测试,用 4 * 10 000 = 40 000 QPS 对 PostgreSQL 进行测试:

MySQL | PostgreSQL

Total test duration: PT14.473S | PT6.337S
Queries duration: PT13.62S | PT5.671S

Executed queries: 50000

Wanted queries rate: 5000/s | 10000/s
Actual queries rate: 3671/s | 8816/s

Min: 8.475 ms | 1.35 ms
Max: 128.404 ms | 27.007 ms
Mean: 29.103 ms | 3.587 ms

Percentile 50 (Median): 28.566 ms | 2.891 ms
Percentile 90: 36.64 ms | 6.126 ms
Percentile 99: 53.419 ms | 11.209 ms
Percentile 99.9: 122.303 ms | 18.949 m

差一点了!象能够处理 8816 TPS(每秒事务数),相当于 4 * 8816 = 35 264 QPS;海豚的最高值达到 3671 TPS,相当于 4 * 3671 = 14 684 QPS – PostgreSQL 的吞吐量高出 2.4 倍 

大象能够处理更多的事务,并且以更低的延迟完成。

插入、更新、删除和选择

按 ID 插入、更新、删除和选择用户 – 按 ID 插入、更新、删除和选择用户,读:写比例为 1:1。也就是说,对于每 3 次按 ID 选择用户,就有 1 次用户插入、1 次按 ID 用户更新和 1 次用户删除。它测试混合负载,同时读取和写入;期望的速率是 7500 QPS

MySQL | PostgreSQL

Total test duration: PT12.313S | PT10.299S
Queries duration: PT11.905S | PT10.116S

Executed queries: 75000
  insert-users: 12425 | 12349
  update-user-emails-by-id: 12343 | 12481
  delete-users-by-id: 12582 | 12399
  select-users-by-id: 37650 | 37771

Wanted queries rate: 7500/s
Actual queries rate: 6300/s | 7413/s

Min: 0.092 ms | 0.081 ms
Max: 87.487 ms | 26.09 ms
Mean: 12.813 ms | 1.154 ms

Percentile 50 (Median): 1.174 ms | 0.369 ms
Percentile 90: 30.671 ms | 2.545 ms
Percentile 99: 40.635 ms | 3.068 ms
Percentile 99.9: 63.811 ms | 9.014 ms

PostgreSQL 以更高的吞吐量和更低的延迟获胜,但这远非最终结论。再次运行案例,使用 25 000 QPS

PostgreSQL

Total test duration: PT11.506S
Queries duration: PT10.665S

Executed queries: 250000
  insert-users: 41775
  update-user-emails-by-id: 42164
  delete-users-by-id: 41420
  select-users-by-id: 124641

Wanted queries rate: 25000/s
Actual queries rate: 23441/s

Min: 0.087 ms
Max: 19.568 ms
Mean: 1.372 ms

Percentile 50 (Median): 0.997 ms
Percentile 90: 2.805 ms
Percentile 99: 4.634 ms
Percentile 99.9: 11.616 ms

因此,象群能够处理这个负载的 23,441 QPS,而海豚只能处理 6,300 QPS。 这意味着在混合工作负载方面,Postgres 的优势是 3.72 倍 

摘要

PostgreSQL(大象),在几乎所有场景中都优于 MySQL(海豚 ):在总共执行的 17 个测试用例中,PostgreSQL 赢了 14 个,有 1 个平局。使用 每秒查询数(QPS) 来衡量吞吐量(越高越好), 平均值和 99 分位数 来衡量延迟(越低越好),以下是 PostgreSQL 表现更优的高层次总结:

  1. 插入
    • 1.05 – 4.87倍更高的吞吐量
    • 延迟降低3.51 – 11.23倍(平均值)和4.21 – 10.66倍(99分位数)
    • PostgreSQL 在单行插入方面提供 21 338 QPS with 4.009 ms at the 99th percentile ,而与 MySQL 的 4,383 QPS & 42.729 ms 相比;对于 100 行 的批量插入,它实现 3535 QPS with 34.779 ms at the 99th percentile ,而与 MySQL 的 1,883 QPS & 146.497 ms 相比
  2. 选择
    • 1.04 – 1.67 倍更高的吞吐量
    • 平均延迟降低 1.67 – 2 倍,99 百分位延迟降低 1.25 – 4.51 倍
    • PostgreSQL 通过 id 进行单行查询时,性能为 55 200 QPS with 5.446 ms at the 99th percentile ,而 MySQL 的性能为 33,469 QPS & 12.721 ms;对于多行排序查询,PostgreSQL 的性能为 4745 QPS with 9.146 ms at the 99th percentile ,而 MySQL 的性能为 4,559 QPS & 41.294 ms
  3. 更新
    • 4.2 – 4.82倍更高的吞吐量
    • 平均延迟降低6.01 – 10.6倍,99分位数延迟降低7.54 – 8.46倍
    • Postgres 通过多列的 ID 更新,而 MySQL 为 3747 QPS & 39.774 ms
  4. 删除
    • 3.27 – 4.65倍更高的吞吐量
    • 平均延迟降低10.24倍 – 10.98倍,99分位数延迟降低9.23倍 – 10.09倍
    • Postgres 通过 id 删除操作 18 285 QPS with 4.661 ms at the 99th percentile ,而 MySQL 为 5596 QPS & 43.039 ms
  5. 插入、更新、删除和查询混合操作
    • 3.72倍更高的吞吐量
    • 平均降低了9.34倍,99分位数降低了8.77倍的低延迟
    • Postgres 在这个 1:1 写入:读取比例的混合负载下交付 23 441 QPS with 4.634 ms at the 99th percentile ,与 MySQL 的 6300 QPS & 40.635 ms 相比


这里是对所有测试用例的更详细总结:

  1. 插入 – 用户表的单行数据
    • MySQL – 4383 QPS; 平均值:26.801 ms,99 百分位数:42.729 ms
    • Postgres – 21 338 QPS; 平均值:2.386 ms,99 百分位数:4.009 ms
    • Postgres 以 4.87 倍的吞吐量优势获胜,平均延迟低 11.23 倍,99 百分位数低 10.66 倍
  2. 插入 – 批量插入100行商品表数据
    • MySQL – 200 QPS; 平均值:26.504 毫秒,99 分位数:45.759 毫秒
    • Postgres – 211 QPS; 平均值:4.1 毫秒,99 分位数:6.88 毫秒
    • Postgres 在吞吐量上领先 1.05 倍,平均延迟低 6.46 倍,99 分位数延迟低 6.65 倍
  3. 插入 – 100 行订单表的批量插入
    • MySQL – 1883 QPS; 平均值:51.606 ms,99 百分位数:146.497 ms
    • Postgres – 3535 QPS; 平均值 14.697 ms,99 百分位数:34.779 ms
    • Postgres 以 1.88 倍的吞吐量优势获胜,平均延迟低 3.51 倍,99 百分位数低 4.21 倍
  4. 插入 – 1000 行 order_item 表数据
    • MySQL – 543 QPS; 平均值:247.138 毫秒,99 百分位数:482.361 毫秒
    • Postgres – 389 QPS; 平均值:192.304 毫秒,99 百分位数:394.913 毫秒
    • MySQL 在吞吐量上获胜,高 1.4 倍,但在延迟上处于劣势,平均值低 1.29 倍,99 百分位数低 1.22 倍,因此 Postgres 获胜 – 因此结果是平局
  5. 选择 – 按用户 ID
    • MySQL – 33 469 QPS; 平均值:1.579 ms,99 百分位:12.721 ms
    • Postgres – 55 200 QPS; 平均值:0.874 ms,99 百分位:5.446 ms
    • PostgreSQL 以 1.65 倍更高的吞吐量获胜,平均延迟降低了 1.8 倍,99 分位数延迟降低了 2.34 倍。
  6. 选择 – 通过电子邮件选择用户
    • MySQL – 31 988 QPS; 平均值:1.772 ms,99 百分位:12.865 ms
    • PostgreSQL – 53 487 QPS;平均:0.834 毫秒,99 百分位:5.358 毫秒
    • PostgreSQL 以 1.67 倍更高的吞吐量获胜,平均延迟降低 2.12 倍,99 百分位延迟降低 2.4 倍
  7. 选择 – 按用户 ID 页面排序,大小为 10 到 100
    • MySQL – 4559 QPS;平均:3.118 毫秒,99 百分位:41.294 毫秒
    • PostgreSQL – 4745 QPS;平均:1.556 毫秒。99 百分位:9.146 毫秒
    • PostgreSQL 以 1.04 倍更高的吞吐量获胜,平均延迟降低 2 倍,99 分位数延迟降低 4.51 倍。
  8. 选择 – 按 id 排序,与多对一用户关联
    • MySQL – 29 223 QPS; 平均值:1.739 ms,99 百分位:14.543 ms
    • Postgres – 28 194 QPS; 平均值:1.897 ms,99 百分位数:19.823 ms
    • MySQL 在吞吐量上胜出,比 Postgres 高出 1.04 倍,平均延迟低 1.09 倍,99 百分位数低 1.36 倍
  9. 选择 – 按 id 排序,与多对多关系 order_item 连接,与多对多关系 item 连接
    • MySQL – 22 619 QPS; 平均值:2.824 ms,99 百分位数:19.795 ms
    • Postgres – 20 211 QPS; 平均值:2.799 ms,99 百分位数:28.604 ms
    • MySQL 在吞吐量上领先 1.12 倍,延迟在平均值上高 1.01 倍(略差),在 99 百分位数上低 1.45 倍
  10. 选择 – 通过 id 查询用户,与一对多订单连接,并计算一些聚合函数
    • MySQL – 22 851 QPS; 平均值:2.759 ms,99 百分位数:19.511 ms
    • Postgres – 31 693 QPS; 平均值:1.648 ms,99 百分位数:15.651 ms
    • Postgres 以 1.39 倍更高的吞吐量获胜,平均延迟低 1.67 倍,99 百分位数低 1.25 倍
  11. 更新 – 通过索引的电子邮件列的 ID 来更新用户
    • MySQL – 3762 QPS; 平均值:26.337 ms,99 百分位数:36.415 ms
    • Postgres – 18 088 QPS;平均:2.483 毫秒,99 百分位:4.827 毫秒
    • PostgreSQL 以 4.8 倍更高的吞吐量获胜,平均延迟低 10.6 倍,99 分位数延迟低 7.54 倍
  12. 更新 – 基于未索引的 updated_at 列的用户 ID
    • MySQL – 4408 QPS;平均:15.172 毫秒,99 分位数:37.726 毫秒
    • PostgreSQL – 18 515 QPS;平均:2.524 毫秒,99 分位数:4.977 毫秒
    • PostgreSQL 以 4.2 倍更高的吞吐量获胜,平均延迟降低 6.01 倍,99 百分位延迟降低 7.58 倍
  13. 更新 – 通过多个列的 ID 更新用户
    • MySQL – 3747 QPS;平均:26.284 毫秒,99 百分位:39.774 毫秒
    • PostgreSQL – 18 046 QPS;平均:2.507 毫秒,99 百分位:4.704 毫秒
    • PostgreSQL 以 4.82 倍更高的吞吐量获胜,平均延迟降低 10.48 倍,99 分位数延迟降低 8.46 倍
  14. 删除 – 按 id 排序
    • MySQL – 5596 QPS; 平均值:20.563 ms,99 百分位:43.039 ms
    • Postgres – 18 285 QPS;平均:2.009 ms,99 百分位:4.661 ms
    • Postgres 在吞吐量上领先 3.27 倍,平均延迟低 10.24 倍,99 百分位低 9.23 倍
  15. 删除操作 – 按 id 批量删除 100 行
    • MySQL – 620 QPS;平均:181.728 ms,99 百分位:670.586 ms
    • Postgres – 2881 QPS;平均:16.547 ms,99 百分位:66.48 ms
    • Postgres 在吞吐量上以 4.65 倍的优势获胜,平均延迟低 10.98 倍,99 百分位低 10.09 倍
  16. 事务 – 一个用户的插入,一个订单和两个订单项
    • MySQL – 3671 QPS;平均:29.103 ms,99 百分位:53.419 ms
    • Postgres – 8816 QPS; 平均值:3.587 ms,99 百分位数:11.209 ms
    • Postgres 以 2.4 倍更高的吞吐量获胜,平均延迟低 8.11 倍,99 百分位数低 4.77 倍
  17. 插入、更新、删除和选择 – 按用户 id 混合,在 1:1 写读比例中
    • MySQL – 6300 QPS; 平均值:12.813 ms,99 百分位:40.635 ms
    • Postgres – 23 441 QPS;平均:1.372 毫秒,99 百分位数:4.634 毫秒
    • Postgres 在吞吐量上领先 3.72 倍,平均延迟低 9.34 倍,99 百分位数低 8.77 倍

原文链接:https://binaryigor.com/mysql-vs-postgresql-performance.html

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容