Learn MySQL Performance

Efficient MySQL Performance distills 20 years of MySQL expertise into 344 pages. Written for software developers, not DBAs, it's easy to digest even if you're new to MySQL.

The nine-step path below is an efficient way through the jungle of MySQL performance topics. Avoid pitfalls! Learn these topics in this order, which is (not coincidentally) the same order as chapters in the book.

"Daniel does a great job of showing how to drive to the fastest resolution without getting lost in guesswork. He also covers InnoDB row locking in a detailed yet digestible form."
—Vadim Tkachenko, CTO, Percona

"This book is different from other MySQL books—it focuses on what matters most: query response time. A must-have for MySQL users!"
—Frédéric Descamps, MySQL Community Manager, Oracle Belgium

"Hands down [the] best technical book I've ever read, and I've been working in this field for close to 30 years."
—Adam (verified Amazon review)

Extremely well written and accessible —reddit comment

MySQL Articles

mlrd: DynamoDB-Compatible API on MySQL

mlrd ("mallard") is a DynamoDB-compatible API that runs on MySQL.

Learn MySQL Performance

A nine-step learning path through MySQL performance in the same order as Efficient MySQL Performance, designed to be the most efficient route to learn MySQL performance.

Monitoring Multi-threaded Replication Lag With Performance Schema

With multi-threaded replication, Seconds_Behind_Source is no longer a reliable lag metric. Part 1 of a 3-part series on monitoring lag correctly with Performance Schema tables.

Replica Preserve Commit Order and Measuring Lag

replica_preserve_commit_order determines whether a replica commits transactions in source order under multi-threaded replication, with consequences for how lag is measured.

Efficient MySQL Performance In 10 Sentences

All 10 chapters of Efficient MySQL Performance, from "Performance is query response time" to the final chapter, each distilled to a single sentence.

Group Commit and Transaction Dependency Tracking

Part 1 of 3: understanding binary log group commit and transaction dependency tracking, the foundation for how multi-threaded replication works in MySQL 8.0.

Lessons From 20 Years Hacking MySQL (Part 1)

Reflections on 20 years hacking MySQL and software engineering.

Lessons From 20 Years Hacking MySQL (Part 2)

A relational database is more than a data bank: it's applied philosophy. The second and final part of lessons from 20 years hacking MySQL.

Why MySQL Replication Is Fast

Replication lag gets all the attention, but MySQL replication is actually remarkably fast. A controlled experiment with Performance Schema and binary log inspection shows exactly why.

When COMMIT Is the Slowest Query

When COMMIT appears as your slowest query, the root cause is almost always slow storage. Here's how to confirm it and what to do about it.

The Infamous ORDER BY LIMIT Query Optimizer Bug

For 16 years the MySQL query optimizer has had a bug where LIMIT 1 can be slower than LIMIT 20 and even trigger a full table scan. Here's what's happening and why.

The Future of MySQL Schema Change: Spirit

Spirit is a new online schema change tool by MySQL expert Morgan Tocker, built to improve on both pt-online-schema-change and gh-ost in speed and safety.

Deferred Join: A Deep Dive

Deferred join is an SQL rewrite that can make a paginated query 2x faster or more, but it's widely misunderstood. This deep dive shows exactly how and why it works.

Announcing Finch: A New MySQL Benchmarking Tool

Finch is a new declarative MySQL benchmarking tool for experts and modern infrastructure, designed to handle the workloads and flexibility that sysbench cannot.

Are Aurora Performance Claims True?

Amazon claims Aurora delivers "Up to 5X the throughput of MySQL." Deep benchmarking digs past the marketing to find out if it's actually true.

Announcing Blip: A New MySQL Monitor

Blip is a new MySQL monitor that rethinks metrics collection from the ground up, solving problems that existing open-source monitors don't address.

COMMIT Latency: Aurora vs. RDS MySQL 8.0

COMMIT is when MySQL pays the storage latency cost to make writes durable. Benchmarking Aurora v2, Aurora v3, and RDS MySQL 8.0 reveals how much that cost differs across AWS managed databases.

Blip: A New Open Source MySQL Metrics Collector

Blip v1.0.0 ships: an open-source MySQL metrics collector purpose-built from the ground up to be the last and greatest MySQL monitor ever.

MySQL IOPS for Reads and Surprsies

MySQL I/O tuning focuses almost entirely on writes, but read IOPS and a few surprising I/O behaviors are worth understanding too.

Is MySQL in the Cloud the End of the DBA?

Cloud MySQL changes the DBA role but doesn't end it, and the implications for software engineers using (not managing) MySQL are significant.

How Not to Use MySQL

The unwritten chapter 9 of Efficient MySQL Performance: how not to use MySQL, including the ways MySQL's reliability makes it too easy to misuse.

Mining the MySQL Performance Schema for Transactions

The Performance Schema holds a rich history of transaction execution: query timings, idle gaps, and more. This post shows how to mine it for a transaction report MySQL tooling doesn't provide.

MySQL Transaction Reporting

MySQL transactions are important but almost nobody monitors them. This post explores what the Performance Schema makes possible and why transaction reporting tooling barely exists.

Better Replication Heartbeats

Heartbeat tables have measured MySQL replication lag for over a decade, but with multi-threaded replication (MTR) the approach has limitations. Can we do better?

InnoDB Page Flushing Diagram

InnoDB page flushing is one of MySQL's most complex internals. This post diagrams the whole process in one visual.

I Don't Want to Shard (MySQL)

Sharding MySQL is a last resort, not a first move. Let's look at why engineers reach for sharding prematurely and what to try instead.

Access Patterns for MySQL

Access patterns are talked about constantly but rarely enumerated. This post catalogues the specific ways applications access MySQL and why each one matters for performance.

Performance Is Less

MySQL performance is about doing less, not more. A look at why reducing what MySQL does is the most powerful performance strategy.

MySQL EXPLAIN ANALYZE

EXPLAIN ANALYZE is indispensable for understanding query execution, but its output isn't easy to interpret. This post closely examines three real examples of its output.

Configuring MySQL Query Metrics

Configuring MySQL query metrics (slow query log, Performance Schema) is skipped in most books but critical in practice. This post covers what chapter 1 of Efficient MySQL Performance left out.

Efficient MySQL Performance

After 17 years with MySQL, I wrote a book unlike any MySQL book before, focused on what actually matters for engineers, not DBAs.

MySQL LRU Flushing and I/O Capacity

InnoDB background LRU flushing is not constrained by innodb_io_capacity or innodb_io_capacity_max. Here's the proof.

MySQL Data Locks: Mapping 8.0 to 5.7

MySQL 8.0 moved data lock information to performance_schema.data_locks. A visual mapping shows how the new output corresponds to what used to be buried in SHOW ENGINE INNODB STATUS.

MySQL Password Rotation with AWS Secrets Manager and Lambda

Automating MySQL password rotation at scale with AWS Secrets Manager, Lambda, and Terraform is far more complex than it appears. Here's a detailed guide that covers all of it.

Query Metrics Requirements for MySQL

What does a production-ready query metrics system actually need?

What the Flush?

A technical deep dive into InnoDB dirty page flushing: what it is, what controls it, and why tuning it matters for consistent MySQL write performance.

21 Parameter Group Values to Change in Amazon RDS for MySQL

21 MySQL 5.7 system variables to change from their RDS defaults, with the MySQL default, the AWS default, and the recommended value.

Missing Writes with MySQL GTID

GTID auto-positioning makes failover feel safe, but it can silently accept a replica that missed writes from a crashed primary. Here's how to detect the data loss.

MySQL Threads Running

QPS measures throughput, but Threads_running reveals how hard MySQL is actually working. It's one of the most important MySQL metrics to monitor.

Queries Effect Performance

Queries don't merely affect MySQL performance, they are the cause of it. When hardware is healthy, queries are responsible for performance, which means they can also fix it.

Fixing Ghosted GTIDs

Ghosted GTIDs—gaps in the executed GTID set silently break auto-positioning and replication topology changes. Here's how to detect them and fix them.

When MySQL Goes Away

Handling MySQL connection errors in Go requires dealing with server error codes, driver errors, sql package errors, and network errors all at once. A practical guide to getting it right.

Crash-safe MySQL Replication

Crash-safe replication is widely misunderstood; most guides add unnecessary settings. This visual guide shows exactly which configuration is necessary and sufficient.

MySQL Select and Sort Status Variables

MySQL Select% and Sort% status variables are ancient diagnostics that remain essential for understanding query performance. This is the updated guide for MySQL 8.0.