This has results for modern Postgres and MySQL using write-heavy tests from sysbench and a large server. I think there are regressions in Postgres that arrive in some of versions 16, 17, 18 and 19 beta1 but I am far from certain and this blog post is just another step in my journey to figure that out.tl;drPostgres suffers a lot from throughput variation while MySQL+InnoDB does notInnoDB gets much better average throughput on 6 of 10 tests, similar throughput one one and then Postgres does better on 3 of 10 testsFor tests from which I provided vmstat and iostat results, Postgres does more write IO per operation. In some cases InnoDB uses more CPU, in other cases it does not.Builds, configuration and hardwareI compiled:Postgres from source for versions 15.17, 16.13, 17.9 and 18.3.MySQL from source for version 8.4.7I used a 48-core server from Hetzneran ax162s with an AMD EPYC 9454P 48-Core Processor with SMT disabled2 Intel D7-P5520 NVMe storage devices with RAID 1 (3.8T each) using ext4128G RAMUbuntu 24.04Configuration files for Postgres:the config file is named conf.diff.cx10a_c32r128 (x10a_c32r128) and is here for versions 15, 16 and 17.for Postgres 18 I used conf.diff.cx10b_c32r128 (x10b_c32r128) which is as close as possible to the Postgres 17 config and uses io_method=syncBenchmarkI used sysbench and my usage is explained here. Normally I run 32 of the 42 microbenchmarks listed in that blog post using tables small enough to be cached by the DBMS. Most test only one type of SQL statement.The tests can be called microbenchmarks. They are very synthetic. But microbenchmarks also make it easy to understand which types of SQL statements have great or lousy performance. Performance testing benefits from a variety of workloads -- both more and less synthetic.But I did things differently here:I only run the write-heavy tests (to save time)The tables are larger than memory and cannot be cachedEach test (microbenchmark) is run for 2 hours when I normally run each for 15 minutesAfter each test a vacuum is doneThe purpose is to search for regressions from new CPU overhead and mutex contention related to MVCC GC (vacuum for Postgres, purge for InnoDB).ResultsI provide charts below with relative QPS. The relative QPS is the following:(QPS for some version) / (QPS for Postgres 15.17)When the relative QPS is > 1 then some version is faster than base version. When it is < 1 then there might be a regression. When the relative QPS is 1.2 then some version is about 20% faster than base version.The per-test results from vmstat and iostat can help to explain why something is faster or slower because it shows how much HW is used per request, including CPU overhead per operation (cpu/o) and context switches per operation (cs/o) which are often a proxy for mutex contention.Results: writesThe table below has relative QPS for Postgres 16 to 19 and then InnoDB all relative to the throughput for Postgres 15.17. Columns 1 to 4 have results for Postgres and the numbers in yellow highlight the tests where there is a regression in Postgres. For column 5 (MySQL with InnoDB) the numbers in yellow and red indicate tests where InnoDB\'s throughput is less than Postgres. And then the numbers in green indicate tests where InnoDB\'s throughput is much larger than Postgres.Note that when relative QPS (rQPS) is 0.90 then throughput dropped by ~10%.Summary:throughput for Postgres drops after version 15.17. I don\'t know yet whether this is a regression.throughput for InnoDB is much better than Postgres in 6 of 10 tests, similar in one test, and much worse in 3 of 10 tests.The sections that follow this one have more detail on results from the update-index, update-zipf tests and insert tests.Relative to: Postgres 15.17col-1 : Postgres 16.13col-2 : Postgres 17.9col-3 : Postgres 18.3col-4 : Postgres 19 beta1col-5 : MySQL 8.4.7col-1 col-2 col-3 col-4 col-50.94 0.97 0.98 1.02 1.88 update-inlist0.94 0.90 0.88 0.92 1.43 update-index0.91 0.86 0.87 0.92 1.19 update-nonindex0.96 0.99 0.98 0.98 0.71 update-one0.92 0.83 0.81 0.85 0.93 update-zipf0.95 0.93 0.84 0.81 1.71 write-only0.94 0.94 0.90 0.92 1.14 read-write_range=100.95 0.96 0.95 0.95 1.93 read-write_range=1000.89 0.82 0.80 0.84 1.01 delete1.05 1.05 1.01 1.10 0.53 insertResults: update-indexSummary:Postgres suffers from too much varianceAverage throughput is ~1.55X larger for InnoDB than for PostgresPer operation, Postgres does ~1.20X more write IO (KB written) to storage than InnoDBPer operation, InnoDB uses more CPU and does more context switches. While autovacuum was enabled and was likely running during the test, my measurements exclude the manual vacuum done at the end of each test.iostat, vmstat normalized by operation rater/s rMB/s w/s wMB/s r/o rKB/o wKB/o o/s dbms35503.0 373.7 58795.7 1345.1 1.375 14.824 53.351 25817 PG 19b133140.6 517.8 53449.6 1735.3 0.827 13.226 44.326 40090 MySQL 8.4.7cs/s cpu/s cs/o cpu/o dbms176167 14.4 6.824 .000557 PG 19b1661395 41.9 16.498 .001046 MySQL 8.4.7Results: update-zipfSummary:Postgres suffers from too much varianceAverage throughput is ~1.09X larger for InnoDB than for PostgresPer operation, Postgres does ~1.30X more write IO (KB written) to storage than InnoDBPer operation, InnoDB uses more CPU and does more context switches. While autovacuum was enabled and was likely running during the test, my measurements exclude the manual vacuum done at the end of each test.iostat, vmstat normalized by operation rater/s rMB/s w/s wMB/s r/o rKB/o wKB/o o/s dbms55595.5 620.7 64264.4 1352.3 0.622 7.110 15.490 89396 PG 19b127405.9 428.2 37465.1 1133.6 0.282 4.508 11.933 97270 MySQL 8.4.7cs/s cpu/s cs/o cpu/o dbms424392 27.2 4.747 .000304 PG 19b11213054 44.5 12.471 .000458 MySQL 8.4.7Results: insertSummary:Postgres suffers from too much varianceAverage throughput is ~2.06X larger for Postgres than for InnoDBPer operation, Postgres does ~1.67X more write IO (KB written) to storage than InnoDBPer operation, Postgres uses more CPU and does more context switches. This is the opposite of what happens above for update-index and update-zipf.iostat, vmstat normalized by operation rater/s rMB/s w/s wMB/s r/o rKB/o wKB/o o/s dbms1615.5 56.0 15321.7 1170.9 0.007 0.242 5.059 237009 PG 19b13.6 0.1 8275.4 340.7 0.000 0.000 3.029 115155 MySQL 8.4.7cs/s cpu/s cs/o cpu/o dbms1214563 46.0 10.547 .000399 PG 19b1800827 50.5 3.379 .000213 MySQL 8.4.7
Write-heavy sysbench tests, a large server, modern Postgres and MySQL appeared first on MariaDB.org
This has results for modern Postgres and MySQL using write-heavy tests from sysbench and a large server. I think there are regressions in Postgres that arrive in some of versions 16, 17, 18 and 19 beta1 but I am far from certain and this blog post is just another step in my journey to figure that out.
tl;dr
Builds, configuration and hardware
I compiled:
I used a 48-core server from Hetzner
Configuration files for Postgres:
Benchmark
I used sysbench and my usage is explained here. Normally I run 32 of the 42 microbenchmarks listed in that blog post using tables small enough to be cached by the DBMS. Most test only one type of SQL statement.
The tests can be called microbenchmarks. They are very synthetic. But microbenchmarks also make it easy to understand which types of SQL statements have great or lousy performance. Performance testing benefits from a variety of workloads -- both more and less synthetic.
But I did things differently here:
The purpose is to search for regressions from new CPU overhead and mutex contention related to MVCC GC (vacuum for Postgres, purge for InnoDB).
Results
I provide charts below with relative QPS. The relative QPS is the following:
(QPS for some version) / (QPS for Postgres 15.17)
When the relative QPS is > 1 then some version is faster than base version. When it is < 1 then there might be a regression. When the relative QPS is 1.2 then some version is about 20% faster than base version.
The per-test results from vmstat and iostat can help to explain why something is faster or slower because it shows how much HW is used per request, including CPU overhead per operation (cpu/o) and context switches per operation (cs/o) which are often a proxy for mutex contention.
Results: writes
The table below has relative QPS for Postgres 16 to 19 and then InnoDB all relative to the throughput for Postgres 15.17. Columns 1 to 4 have results for Postgres and the numbers in yellow highlight the tests where there is a regression in Postgres. For column 5 (MySQL with InnoDB) the numbers in yellow and red indicate tests where InnoDB's throughput is less than Postgres. And then the numbers in green indicate tests where InnoDB's throughput is much larger than Postgres.
Note that when relative QPS (rQPS) is 0.90 then throughput dropped by ~10%.
Summary:
The sections that follow this one have more detail on results from the update-index, update-zipf tests and insert tests.
Relative to: Postgres 15.17
col-1 : Postgres 16.13
col-2 : Postgres 17.9
col-3 : Postgres 18.3
col-4 : Postgres 19 beta1
col-5 : MySQL 8.4.7
col-1 col-2 col-3 col-4 col-5
0.94 0.97 0.98 1.02 1.88 update-inlist
0.94 0.90 0.88 0.92 1.43 update-index
0.91 0.86 0.87 0.92 1.19 update-nonindex
0.96 0.99 0.98 0.98 0.71 update-one
0.92 0.83 0.81 0.85 0.93 update-zipf
0.95 0.93 0.84 0.81 1.71 write-only
0.94 0.94 0.90 0.92 1.14 read-write_range=10
0.95 0.96 0.95 0.95 1.93 read-write_range=100
0.89 0.82 0.80 0.84 1.01 delete
1.05 1.05 1.01 1.10 0.53 insert
Results: update-index
Summary:
iostat, vmstat normalized by operation rate
r/s rMB/s w/s wMB/s r/o rKB/o wKB/o o/s dbms
35503.0 373.7 58795.7 1345.1 1.375 14.824 53.351 25817 PG 19b1
33140.6 517.8 53449.6 1735.3 0.827 13.226 44.326 40090 MySQL 8.4.7
cs/s cpu/s cs/o cpu/o dbms
176167 14.4 6.824 .000557 PG 19b1
661395 41.9 16.498 .001046 MySQL 8.4.7
Results: update-zipf
Summary:
iostat, vmstat normalized by operation rate
r/s rMB/s w/s wMB/s r/o rKB/o wKB/o o/s dbms
55595.5 620.7 64264.4 1352.3 0.622 7.110 15.490 89396 PG 19b1
27405.9 428.2 37465.1 1133.6 0.282 4.508 11.933 97270 MySQL 8.4.7
cs/s cpu/s cs/o cpu/o dbms
424392 27.2 4.747 .000304 PG 19b1
1213054 44.5 12.471 .000458 MySQL 8.4.7
Results: insert
Summary:
iostat, vmstat normalized by operation rate
r/s rMB/s w/s wMB/s r/o rKB/o wKB/o o/s dbms
1615.5 56.0 15321.7 1170.9 0.007 0.242 5.059 237009 PG 19b1
3.6 0.1 8275.4 340.7 0.000 0.000 3.029 115155 MySQL 8.4.7
cs/s cpu/s cs/o cpu/o dbms
1214563 46.0 10.547 .000399 PG 19b1
800827 50.5 3.379 .000213 MySQL 8.4.7
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | CPU-bound sysbench on a large server: Postgres 12 to 19 beta1 | 0 | 13.06 | 20-06-2026 |
| 2 | CPU-bound sysbench on a large server: Postgres, MySQL and MariaDB | 0 | 5.53 | 04-04-2026 |
| 3 | HammerDB tproc-c on a large server, Postgres and MySQL | 0 | 6.5 | 15-02-2026 |
| 4 | The insert benchmark on a small server, IO-bound workload : Postgres 19 beta1 | 0 | 14.28 | 17-06-2026 |
| 5 | The insert benchmark on a small server : Postgres 12.22 through 18.3 | 0 | 11.9 | 29-03-2026 |
| 6 | Sysbench vs MySQL on a small server: no new regressions, many old ones | 0 | 8.8 | 24-03-2026 |
| 7 | Sysbench vs MySQL on a small server: another way to view the regressions | 0 | 9.01 | 09-04-2026 |
| 8 | MySQL 9.7.0 vs sysbench on a small server | 0 | 8.98 | 10-04-2026 |
| 9 | The insert benchmark on a small server, cached workload : Postgres 19 beta1 | 0 | 15.89 | 11-06-2026 |
| 10 | CPU efficiency for MariaDB, MySQL and Postgres on TPROC-C with a small server | 0 | 4.26 | 16-03-2026 |