io_uring 快吗? Postgres 17 与 18 的基准测试

Postgres 17 与 18 的基准测试

Postgres 18 于几周前发布,它的改进引起了大量炒作。最值得注意的是,Postgres 18 引入了 io_method 配置选项 ,允许用户更好地控制磁盘 I/O 的处理方式。

将其设置为 sync 会导致与 17 及更早版本相同的行为。通过此设置,所有 I/O 都通过同步请求进行。

18 引入了两种替代方案: workerio_uring (默认 worker )使 Postgres 使用专用的后台工作进程来处理所有 I/O 操作 io_uring 是许多人出于性能原因而兴奋的变化,因为它使用 Linux io_uring 接口允许所有磁盘读取异步进行。希望这可以显着提高 I/O 性能。

我们进行了详细的基准测试来比较 Postgres 17 和 18 的性能。让我们看看这些改进是否真的像人们所宣传的那样。

基准配置

sysbench 用于执行基准测试 io_uring 改进仅适用于读取 ,因此这里的重点将放在 oltp_read_only 基准测试上。这包括 点查询 和 范围扫描 和 聚合查询,这些查询由 --range_size 参数控制。虽然对写入和读/写组合性能进行基准测试也很有趣,但坚持 只读请求 有助于集中讨论。我们将数据大小设置为 TABLES=100SCALE=13000000 这将生成一个 ~300 GB 的数据库(100 个表,每个表有 1300 万行)。

基准测试是在四种不同的 EC2 实例配置上进行的:

Instance vCPUs RAM Disk Disk type IOPS Throughput
r7i.2xlarge 8 64 GB 700 GB gp3 3,000 125 MB/s
r7i.2xlarge 8 64 GB 700 GB gp3 10,000 500 MB/s
r7i.2xlarge 8 64 GB 700 GB io2 16,000 -
i7i.2xlarge 8 64 GB 1,875 GB NVMe 300,000 -

所有这些实例都在相同(或极其相似)的 Intel CPU 上运行。我们使用 i7i 实例,以展示 Postgres 使用快速本地 NVMe 驱动器的能力。这就是我们用于 PlanetScale Metal 的,并且已经看到了 Postgres 17 的惊人性能结果 。许多其他云提供商仅提供一种网络附加存储形式,而我们提供两种选择。

在进行基准测试之前,每个服务器都会经过 10 分钟的查询负载预热。

在每一种配置中,我们都以以下配置运行 sysbench oltp_read_only 基准测试,每次持续 5 分钟:

  • 单个连接和 --range_size = 100
  • 10 个连接和 --range_size = 100
  • 50 个连接和 --range_size = 100
  • 单个连接和 --range_size = 10,000
  • 10 个连接和 --range_size = 10,000
  • 50 个连接和 --range_size = 10,000

这导致总共 24 个 5 分钟基准测试运行。这 24 种配置每种运行四次!在 Postgres 17 上运行一次,在 Postgres 18 上运行一次,使用 io_method=workerio_method=io_uringio_method=sync 。这总共产生了 96 种基准测试组合。

这是一个极其 I/O 密集型的工作负载。数据大小(300 GB)远远超过 RAM 大小(64 GB),因此这里执行的查询将需要大量的磁盘访问。

Single connection 单连接

虽然单个连接是不切实际的生产工作负载,但它为不同的 I/O 设置如何影响直线性能提供了基准。让我们评估一下我们可以在这里实现的 QPS。

以下是所有 单连接 运行的平均 QPS,其中 --range_size 值设置为默认值 100。这意味着完整的读取工作负载由点查询和对 100 行序列进行扫描/聚合的查询组合组成。

有几件事是清楚的:

  1. 在网络附加存储(gp3、io2)上, syncworker 模式下的 Postgres 18 的性能明显优于使用 io_uring 的 17 和 18。我承认,这让我很惊讶!我的预期是 io_uring 性能会与所有这些选项一样好,甚至更好。
  2. gp3 甚至 io2 的延迟显然是造成这种差异的一个因素。在具有低延迟本地 NVME 驱动器 的实例上,所有选项都更加均匀匹配
  3. gp3 甚至非常昂贵的 io2 驱动器的延迟/IOPS 都是一个限制因素。本地磁盘在所有配置中都表现出色。
  4. 对于那些非常简单、短暂执行、几乎没有锁竞争或磁盘 I/O 的查询,Postgres 18 的基础执行速度(CPU级原始性能)比以前的版本快得多 .这是令人兴奋的改进.

这是相同的测试,但使用了 --range_size=10000 。这意味着工作负载具有更大的扫描/聚合,这意味着更多的顺序 I/O 和更低的 QPS:

本地磁盘仍然明显表现优异,但其他三个选项之间的差异不那么明显。这是由于 (a) 更多顺序 I/O 但更重要的是 (b) 更多 CPU 工作(聚合 10k 行比聚合 100 行更耗费 CPU 资源)。此外,postgres 17 和 18 之间的差异要小得多。

下面是一个交互式视觉效果,比较了所有实例类型的 Postgres 17 结果与 Postgres 18 上表现最佳的 workers。单击缩略图可在图表中添加或删除线条,并比较各种组合。这是基于 10 秒的采样率。

High concurrency 高并发

在实际场景中,我们有许多同时发生的连接和许多读取操作。让我们看看这些服务器如何处理相同的基准,但在 50 个连接上负载要高得多。

当然, oltp_read_only 不会捕获真实的 OLTP 工作负载,特别是因为它不包括写入,但我们使用它作为具有高读取需求的工作负载的代理。下面,我们显示了所有 50 个连接 oltp_read_only--range_size=100 的平均 QPS。

现在,随着并行度的提高和 I/O 需求的增加,有几点变得清晰起来:

  1. IOPS 和吞吐量是每个 EBS (根卷存储在 Amazon EBS (Elastic Block Store) 上)支持的实例的明显瓶颈。在这种情况下,不同的版本/ I/O 设置不会产生巨大的差异。
  2. 随着我们提高 EBS 性能,QPS 也同步增长,并且本地 NVME 实例的性能优于所有实例。
  3. 具有 syncworker Postgres 18 在所有 EBS 支持的实例上均以微弱优势获得最佳性能。

同样,基准相同,但使用 --range_size=10000

gp3-10kio2-16k 实例更接近本地磁盘性能。但是,这是因为我们使基准测试更加受 CPU 约束而非受 I/O 约束 ,因此本地磁盘的低延迟优势较小(尽管仍然是最好的!)但重要的是,我们终于有了一个 io_uring 获胜的场景!在 NVMe 实例上,它的性能略优于其他选项。

下面我们再次比较 Postgres 17 和 Postgres 18 worker 的结果。单击缩略图可在图表中添加或删除线条,并比较各种组合。

Moderate concurrency 中等并发

这些相同的基准测试也使用 10 个并发连接执行。结果非常相似,因此不会全部显示,但我确实想指出这个图表,其中 --range_size=100

仔细查看第一个条形组(对于 gp3-3k )。io_uring 设置 io_uring 性能明显差于 其他设置。但是,如果在有 50 个连接时查看图表的同一部分, io_uring 性能仅比其余部分稍差。对我来说,这表明当有大量 I/O 并发时, io_uring 性能良好,但在低并发场景中,它并没有那么有益。

Cost 成本

在比较基础设施设置时,始终应考虑成本。以下是 AWS 中每个服务器配置的按需成本:

  • r7i 搭配 gp3 3k IOPS 和 125 Mbps: 442.32 美元/月
  • r7i 搭配 gp3 10k IOPS 和 500 Mbps: 每月 492.32 美元
  • r7i 搭配 io2 16k IOPS: 每月 1,513.82 美元
  • 带有本地 NVMe(无 EBS)的 i7i : 551.15 美元/月

请记住,前三款只有 700 GB 的存储空间,而 i7i 存储空间为 1.8 TB!带有本地 NVMe 磁盘的服务器显然是性价比最高的。

为什么 io_uring 不是最快的?

鉴于我对 Postgres 18 的新 io_uring 功能感到兴奋,我期待它能在更多场景中获胜。那么这里发生了什么?

首先,这是一种非常特殊的工作负载类型。它是只读的,并且结合了点查询、范围扫描和范围聚合 io_uring 肯定还有其他工作负载可以发挥其作用。通过不同的 postgresql.conf 调整,我们也有可能看到 io_uring 的改进。

在撰写本文时,我偶然发现了 Tomas Vondra 的精彩博客, 其中讨论了新的 io_method 选项、如何调整它们以及每种选项的优缺点。他针对为什么 workers 性能优于 io_uring 提出了几个很好的观点,我建议您阅读一下。简而言之:

  • 索引扫描(尚未)使用 AIO。

  • 尽管 I/O 通过 io_uring 在后台发生,但校验和 / memcpy 仍然可能成为瓶颈。

  • 从单个进程的角度来看, workers 可以实现更好的 I/O 并行性。

因此,在某些情况下, io_uring 并不总是表现得更好!我很乐意看到其他人的进一步基准测试,涵盖配置上的其他工作负载类型。您可以在附录中找到用于这些测试的许多配置。

结论

虽然测试范围很窄,但这是一个有趣的实验,用于比较 Postgres 版本和 I/O 设置的性能。我的主要收获是:

  • Postgres 18 带来了良好的 I/O 改进和配置灵活性。维护团队做得很好!
  • 本地磁盘无疑是赢家。 当拥有低延迟 I/O 和极高的 IOPS 时,其他因素就变得不那么重要了。这就是 PlanetScale Metal 能够提供一流数据库性能的原因。
  • 使用 io_method=worker 作为新的默认设置是一个不错的选择。它具有 io_uring 的许多"异步"优势,而不依赖于特定的内核接口,并且可以通过设置 io_workers=X 进行调整。
  • 不存在一种适合所有情况的最佳 I/O 配置。
  • 尽管确实有好处,但新的 workers I/O 配置对网络附加存储场景的帮助并不像人们希望的那样大。

附录:测试数据库配置

以下是用于此基准测试的一些关键的自定义调整的 Postgres 配置:

properties 复制代码
shared_buffers = 16GB          # 25% of RAM
effective_cache_size = 48GB    # 75% of RAM
work_mem = 64MB
maintenance_work_mem = 2GB

wal_level = replica
max_wal_size = 16GB
min_wal_size = 2GB
wal_buffers = 16MB
checkpoint_completion_target = 0.9

random_page_cost = 1.1
effective_io_concurrency = 200
default_statistics_target = 100

max_worker_processes = 8
max_parallel_workers_per_gather = 4
max_parallel_workers = 8
max_parallel_maintenance_workers = 4

bgwriter_delay = 200ms
bgwriter_lru_maxpages = 100
bgwriter_lru_multiplier = 2.0

autovacuum = on
autovacuum_max_workers = 4
autovacuum_naptime = 10s
autovacuum_vacuum_scale_factor = 0.05
autovacuum_analyze_scale_factor = 0.025

logging_collector = on
...more log configs...

shared_preload_libraries = 'pg_stat_statements'
track_activity_query_size = 2048
track_io_timing = on

jit = on

# io_workers left at default = 3

原文: Postgres 17 与 18 的基准测试(Benchmarking Postgres 17 vs 18 --- PlanetScale)

PostgreSQL 18 中的 AIO 调优(Tuning AIO in PostgreSQL 18 - Tomas Vondra)

相关推荐
程序员侠客行21 小时前
Mybatis连接池实现及池化模式
java·后端·架构·mybatis
Honmaple21 小时前
QMD (Quarto Markdown) 搭建与使用指南
后端
PP东1 天前
Flowable学习(二)——Flowable概念学习
java·后端·学习·flowable
invicinble1 天前
springboot的核心实现机制原理
java·spring boot·后端
Goat恶霸詹姆斯1 天前
mysql常用语句
数据库·mysql·oracle
全栈老石1 天前
Python 异步生存手册:给被 JS async/await 宠坏的全栈工程师
后端·python
大模型玩家七七1 天前
梯度累积真的省显存吗?它换走的是什么成本
java·javascript·数据库·人工智能·深度学习
曾经的三心草1 天前
redis-9-哨兵
数据库·redis·bootstrap
space62123271 天前
在SpringBoot项目中集成MongoDB
spring boot·后端·mongodb
明哥说编程1 天前
Dataverse自定义表查询优化:D365集成大数据量提速实战【索引配置】
数据库·查询优化·dataverse·dataverse自定义表·索引配置·d365集成·大数据量提速