Software

PostgreSQL vs MySQL: Benchmarks and a Decision Table

By · Fri Oct 09 2026 · 7 min read · 0 views

View as a Web Story

Software#postgresql#database-comparison#mysql#benchmark#sql

PostgreSQL vs MySQL benchmark results

PostgreSQL is the better default for most new applications, and MySQL is the better fit when you already run it, need its replication tooling, or serve simple read-heavy traffic. We loaded the same 1,000,000-row orders table into both and timed six queries. PostgreSQL won five of six, and the gap on joins and aggregates was large enough to change an answer you may have read elsewhere.

That result comes with caveats, which we list below. Benchmarks that hide their setup are the main reason this comparison has so much bad advice around it.

PostgreSQL vs MySQL: the short answer

PostgreSQL is an open-source object-relational database known for standards-compliant SQL, rich data types and extensions. MySQL is an open-source relational database owned by Oracle, known for simple operation and a huge installed base. Both store tables, run transactions and speak SQL. The difference is in what each does well by default.

You need Pick
Complex joins, reports, window functions PostgreSQL
JSON documents next to relational tables PostgreSQL
Geospatial data, full-text search, vector search through extensions PostgreSQL
A host that only offers MySQL or MariaDB (many shared plans) MySQL
Mature statement-based and group replication with existing team skills MySQL
Simple CRUD app with no heavy reporting Either; choose what your team knows

If you are starting fresh and have no constraint, choose PostgreSQL. If you are choosing between them because of a CMS such as WordPress, the CMS has already chosen MySQL for you.

How we tested

Everything below ran on one 8-core, 8 GB Mac laptop with both servers on the same disk and default configuration. We did not tune either one.

  • PostgreSQL 18.1, shared_buffers 128 MB, synchronous_commit on. This binary is an x86_64 build running under Rosetta translation.
  • MySQL 9.3.0 (an Innovation release, not an LTS), InnoDB buffer pool 128 MB, innodb_flush_log_at_trx_commit 1. This binary is native arm64.
  • Data: orders with 1,000,000 rows (id, customer_id, status, amount, created_at) and customers with 50,000 rows. Same CSV files loaded into both.
  • Timing: each query ran eight times through the command-line client. We dropped the first run, took the median of seven, and subtracted the median time of SELECT 1 (15 ms for psql, 12 ms for mysql) to remove client startup.

Two of those choices tilt the test. The Rosetta penalty hurts PostgreSQL, and MySQL 9.3 is not the LTS line you would run in production. Treat the numbers as a direction, then rerun them on your own hardware with your own queries. The script is short enough to adapt, and every query is listed in the table below.

Results: six queries on one million rows

Bar chart comparing PostgreSQL 18.1 and MySQL 9.3 median query times in milliseconds for six queries on a 1,000,000-row orders table

Query PostgreSQL 18.1 MySQL 9.3 Faster
Primary-key lookup 1.5 ms 0.5 ms MySQL
Last 20 orders for one customer (indexed) 1.5 ms 3.3 ms PostgreSQL
Revenue by status (full scan, group by) 49 ms 389 ms PostgreSQL, 7.9x
Revenue by month (scan, group, sort) 234 ms 395 ms PostgreSQL, 1.7x
Join orders to customers, group by region 53 ms 638 ms PostgreSQL, 12x
Top 10 customers with rank() window 308 ms 320 ms Tie

Read the table in three parts.

Point lookups are a wash. Both databases answer a primary-key fetch in around a millisecond. The 1 ms gap is inside client noise. Anyone who tells you one engine is "faster for simple reads" is describing a difference you cannot feel in a web request.

Scans and joins are not a wash. PostgreSQL ran the status rollup in 49 ms because its plan used a Gather Merge with two planned parallel workers. MySQL's plan was a single table scan feeding an aggregate in a temporary table. The join result, 53 ms against 638 ms, comes from the same effect plus a hash join on the 50,000-row customers table. If your dashboards run on the same database as your app, this is the number that matters.

Advertisement

Windows tied. The ranking query spent most of its time sorting 50,000 grouped rows, which neither engine could parallelize much.

You can confirm the parallelism yourself. Run EXPLAIN on the rollup in both servers: PostgreSQL shows Gather Merge with Workers Planned: 2, and MySQL's EXPLAIN FORMAT=TREE shows Aggregate using temporary table. The PostgreSQL parallel query documentation lists when the planner chooses it and which settings cap it.

Loading data and storage

Bar chart of load time, table size and 5,000 single-row insert time for PostgreSQL 18.1 and MySQL 9.3

Measure PostgreSQL 18.1 MySQL 9.3
Bulk load 1,000,000 rows (COPY vs LOAD DATA) 0.68 s 3.70 s
Add primary key and two indexes 1.65 s 2.01 s
Table plus indexes on disk 108 MB 87 MB
5,000 single-row autocommit inserts 0.21 s 0.40 s

PostgreSQL loaded faster, but its table and indexes took 24% more space. That gap is real and worth knowing: InnoDB clusters the table on the primary key and stores rows compactly, while PostgreSQL keeps a larger tuple header per row. At 100 million rows the difference becomes gigabytes of disk and cache.

The single-row insert row needs a caution. Both servers were durable by their defaults, but macOS flushes to disk differently from a Linux server, so absolute write numbers on a laptop mean little. Compare write speed on the hardware you will deploy to. Our migration notes show how much load method matters on their own: in our migration process post COPY beat one-row INSERT statements by 42 times.

What the benchmark cannot tell you

A speed test hides the things that usually decide this choice. Five matter more than milliseconds.

  1. Data types. PostgreSQL has arrays, ranges, jsonb, enums with real type checking, and the numeric type without silent rounding. MySQL has fewer types, and its behavior depends on the SQL mode. Check sql_mode before you trust MySQL to reject bad data.
  2. Extensions. PostgreSQL's extension system gives you PostGIS for geospatial, pg_trgm for fuzzy search and pgvector for embeddings. MySQL has no comparable ecosystem for the same jobs.
  3. Replication and scaling out. MySQL's replication is older and widely understood, and managed services such as Aurora and PlanetScale's Vitess offering are built around it. PostgreSQL's logical replication has closed most of that gap, but your team's experience counts.
  4. Licensing and ownership. PostgreSQL uses its own permissive license and is governed by a community. MySQL is dual-licensed and owned by Oracle, and MariaDB exists as a fork because of that history. For some legal teams this alone decides it.
  5. Versions and support. MySQL 8.0 reached end of life on April 30, 2026 according to a third-party version table, and Oracle's MySQL 9.7 LTS announcement marks the new long-term line from April 2026. On the PostgreSQL side, every major version gets five years of support. Check where your version sits with our PostgreSQL version guide.

Syntax differences that bite when you switch

If you move code between the two, these are the first errors you will see.

Task PostgreSQL MySQL
Quote an identifier "order" `order`
Auto-increment key GENERATED ALWAYS AS IDENTITY AUTO_INCREMENT
Limit rows LIMIT 20 LIMIT 20
Upsert INSERT ... ON CONFLICT DO UPDATE INSERT ... ON DUPLICATE KEY UPDATE
Month bucket date_trunc('month', ts) DATE_FORMAT(ts, '%Y-%m')
String concat a || b CONCAT(a, b)
Case sensitivity of = on text Case-sensitive Depends on collation, usually case-insensitive

The last row causes the most production bugs. A login query that matches Alice@example.com against alice@example.com works on MySQL by accident and fails on PostgreSQL. Normalize emails to lowercase on write and the problem disappears on both.

A decision flow you can follow

Decision flowchart: start with PostgreSQL unless a host, CMS or team constraint forces MySQL; use MySQL LTS for forced cases

Ask these in order and stop at the first yes.

  1. Does your CMS, framework plugin or host require MySQL? Use MySQL, and pick an LTS release.
  2. Do you need JSON plus joins, geospatial, vector search or heavy reporting? Use PostgreSQL.
  3. Does your team already operate one of them well? Use that one. Operations skill beats a 10% engine difference.
  4. Still tied? Use PostgreSQL. It has the longer feature runway for the things teams usually add later.

Moving later is possible but not free. Plan on a rehearsal, a type-mapping pass and a verification step, and use the tools covered in our database migration tools guide.

Advertisement

FAQ

Is PostgreSQL faster than MySQL?

It depends on the query. In our test PostgreSQL was 8 to 12 times faster on a full-scan rollup and a join, tied on a window query, and about a millisecond slower on a primary-key lookup. Simple lookups are equal for practical purposes.

Why is PostgreSQL better than MySQL for complex queries?

Its planner can run a scan across several parallel workers and it has a wide set of join strategies. The `EXPLAIN` output on our rollup query showed `Workers Planned: 2`, while MySQL's plan used one scan and a temporary table.

Is MySQL still worth using in 2026?

Yes. It runs a huge share of the web, including WordPress, and MySQL 9.7 became a long-term support release in April 2026. Use it when a product requires it or your team runs it well.

Which is easier for beginners?

MySQL is slightly simpler to install and to start with, and `AUTO_INCREMENT` is easier to read than identity columns. PostgreSQL's stricter errors catch more mistakes early, which many teams prefer after the first week.

Can I migrate from MySQL to PostgreSQL?

Yes. Map types first, then load data with a bulk method, then verify row counts and sums on both sides. Tools such as pgloader automate the copy, and a staging rehearsal finds case-sensitivity and date-format surprises before cutover.

Comments

Loading…

Sign in to join the conversation.

Related posts