MySQL vs PostgreSQL Performance: A Comprehensive Throughput & Latency Analysis
#Backend

MySQL vs PostgreSQL Performance: A Comprehensive Throughput & Latency Analysis

Tech Essays Reporter
6 min read

A rigorous performance comparison of MySQL 9.5 and PostgreSQL 18.1 across 17 test cases reveals PostgreSQL's significant advantage in most workloads, with notable exceptions in complex joins where MySQL holds a slight edge.

The performance battle between MySQL and PostgreSQL is a perennial topic in database engineering, often reduced to anecdotal evidence or oversimplified benchmarks. This analysis moves beyond surface-level comparisons, presenting a detailed, multi-dimensional evaluation of both databases across diverse workloads. By simulating real-world scenarios—from single-row operations to complex joins and mixed transactional loads—we can observe how architectural differences translate into measurable performance outcomes.

Featured image

Methodology & Environment

To ensure reproducibility and fair comparison, both databases were containerized with Docker, running on an AMD Ryzen 7 PRO 7840U with 32 GiB of RAM and an NVMe SSD. Each database instance was allocated 16 GiB of memory and 8 CPU cores, with custom configurations tuned for performance rather than absolute optimization. MySQL 9.5 used an increased innodb_buffer_pool_size (12G) and innodb_redo_log_capacity (2G), while PostgreSQL 18.1 had its shared_buffers set to 4GB and effective_cache_size to 12GB. The transaction isolation level was set to READ-COMMITTED for both to ensure a level playing field.

The test suite, implemented in Java and executed via Docker, comprised 17 distinct test cases. These were designed to stress different aspects of database performance: simple inserts, batch operations, indexed and non-indexed reads, various join types, updates, deletes, and mixed workloads. Connection pool sizing was empirically determined, with MySQL benefiting from a larger pool (128 connections) compared to PostgreSQL (64 connections), particularly for write-heavy loads.

The Test Schema

The schema, defined in PostgreSQL syntax but conceptually similar for MySQL, models a simple e-commerce system with four tables: user, order, item, and order_item. This structure allows for testing a range of relationships: one-to-many (users to orders), many-to-many (orders to items via order_item), and complex queries involving joins and aggregates. The presence of a TEXT column in the item table adds a realistic performance variable, as variable-length text fields can significantly impact insert and update throughput.

Results: A Clear Winner with Nuanced Exceptions

The results, summarized across throughput (queries per second, QPS) and latency (mean and 99th percentile), show PostgreSQL dominating the majority of scenarios. Out of 17 test cases, PostgreSQL won 14, with one draw and only two victories for MySQL.

Inserts: PostgreSQL's Dominance

For single-row inserts (500,000 users), PostgreSQL achieved 21,338 QPS with a mean latency of 2.386 ms, compared to MySQL's 4,383 QPS and 26.801 ms. This represents a 4.87x throughput advantage for PostgreSQL, with latency improvements of over 11x. Batch inserts (100 rows) showed a similar trend, though the gap narrowed. PostgreSQL's advantage is most pronounced in simple, high-volume writes, where its MVCC (Multi-Version Concurrency Control) architecture and efficient write path excel.

A notable exception was the batch insert of 1,000 order_item rows, where MySQL achieved 543 QPS versus PostgreSQL's 389 QPS. However, PostgreSQL maintained lower latency, making this a draw rather than a clear win for MySQL.

Selects: Mixed Performance

PostgreSQL excelled at single-row and sorted selects from a single table. For instance, selecting users by ID yielded 55,200 QPS (PostgreSQL) vs. 33,469 QPS (MySQL), with significantly lower latency. Sorted user pages (with random offsets) showed nearly identical throughput (4,745 QPS vs. 4,559 QPS), but PostgreSQL's latency was half that of MySQL's at the mean and over 4.5x better at the 99th percentile.

However, MySQL demonstrated a slight edge in certain join operations. In the orders joined with users (many-to-one) test, MySQL achieved 29,223 QPS versus PostgreSQL's 28,194 QPS. Similarly, for the complex double join (many-to-many relationships), MySQL's throughput was 1.12x higher (22,619 QPS vs. 20,211 QPS). This suggests that MySQL's query optimizer may handle specific join patterns more efficiently, or that its storage engine's index structures are better suited for these particular access patterns. Conversely, PostgreSQL won decisively in a join with aggregate functions (SELECT USERS WITH ORDERS STATS BY ID), achieving 31,693 QPS vs. 22,851 QPS.

Updates & Deletes: PostgreSQL's Clear Victory

PostgreSQL's superiority was most dramatic in write operations. For updates, PostgreSQL's throughput was 4.2x to 4.82x higher than MySQL's, with latency reductions of 6x to 10x. For example, updating the indexed email column saw PostgreSQL handle 18,088 QPS with a 99th percentile latency of 4.827 ms, while MySQL peaked at 3,762 QPS with 36.415 ms latency.

Deletes followed a similar pattern. Deleting orders by ID (with cascading deletes to order_item) resulted in 18,285 QPS for PostgreSQL vs. 5,596 QPS for MySQL—a 3.27x advantage. Batch deletions were even more stark: PostgreSQL achieved 2,881 QPS compared to MySQL's 620 QPS (4.65x better), with latency improvements of over 10x.

Transactions & Mixed Workloads

In transactional workloads, PostgreSQL again showed its strength. A transaction inserting a user, an order, and two order items achieved 8,816 transactions per second (35,264 QPS) for PostgreSQL, versus 3,671 TPS (14,684 QPS) for MySQL—a 2.4x throughput advantage. The mixed workload test (1:1 reads to writes) was particularly telling: PostgreSQL handled 23,441 QPS with a mean latency of 1.372 ms, while MySQL managed only 6,300 QPS with 12.813 ms latency. This 3.72x throughput advantage underscores PostgreSQL's ability to maintain performance under concurrent read/write pressure.

Architectural Insights & Trade-offs

The performance differences stem from fundamental architectural choices. PostgreSQL's MVCC model, which avoids locking during reads, likely contributes to its superior read performance under concurrent loads. Its write-ahead logging (WAL) and vacuum processes are highly optimized for modern storage. MySQL's InnoDB, while robust, may incur more overhead in certain write scenarios, particularly with its default Repeatable Read isolation level (though we set it to Read Committed for fairness).

The test environment's configuration also plays a role. MySQL's need for a larger connection pool suggests different concurrency management. The presence of a TEXT column in the item table highlights how data types influence performance; PostgreSQL's handling of large text fields appears more efficient.

Conclusion & Recommendations

For workloads dominated by inserts, updates, deletes, and single-table queries, PostgreSQL is the clear performance leader. Its advantages in throughput and latency are substantial, often by an order of magnitude. MySQL shows a slight edge in specific complex join scenarios, which may be relevant for applications heavily reliant on such queries.

However, performance is only one dimension. The choice between MySQL and PostgreSQL should also consider feature sets, ecosystem support, operational complexity, and specific application requirements. For instance, MySQL's simpler replication and broader tooling might favor certain deployments, while PostgreSQL's advanced features (like JSONB, full-text search, and custom types) offer greater flexibility.

This analysis provides a data-driven foundation for decision-making. The full test suite and results are available in the GitHub repository, allowing for further experimentation and validation. For a visual walkthrough and additional context, including tests with MariaDB on remote infrastructure, see the companion video.

Ultimately, the "best" database depends on your specific use case, but for general-purpose, high-performance applications, PostgreSQL's current implementation demonstrates a compelling performance advantage.

Comments

Loading comments...