The WordPress slow query log is a MySQL file that records every database query that takes longer than a threshold you set, making it the single most useful place to look when your WordPress backend feels slow. It is also the single most misread. People open the file, see hundreds of queries each marked "slow," and either panic and fix the wrong thing or freeze and do nothing because there is too much.

Think of the slow query log like an itemized receipt for a long shopping trip. At first glance, every line looks like a cost. But the trip was not made expensive by the one pricey item you remember. It was made expensive by the cheap thing you bought forty times without noticing. Reading the log in the right order is how you find that forty-times item instead of staring at the single expensive one.

This guide explains what the log contains, how to turn it on safely, and the exact order to read it in so you fix the queries that actually matter, not the ones that merely look scary.

What the WordPress slow query log actually contains

The slow query log records any query that exceeds your configured long_query_time threshold. The default threshold is 10 seconds, which is close to useless, because any query slow enough to cross that line is an obvious problem you would already know about. Set a tighter threshold:

  • Production: 0.5 seconds. Captures queries that hurt the user experience without filling your disk.

  • Diagnostic: 0.1 seconds. Run it for one hour during normal traffic, then revert.

To enable it on a managed host, you usually edit my.cnf (or the equivalent field in your hosting panel):

slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 0.1
log_queries_not_using_indexes = 1

That last line is the one most people forget, and it is the most useful. It logs any query that performs a full table scan, even when the query itself is fast, because a fast scan today becomes a slow one once the table grows. A full table scan means MySQL had to read every row to answer the query, rather than jumping straight to the right ones.

How to read a slow log entry

A single entry looks like this:

# Time: 2026-05-05T09:14:22Z
# Query_time: 0.342  Lock_time: 0.000  Rows_sent: 1  Rows_examined: 89412
SELECT post_id, meta_value FROM wp_postmeta
WHERE meta_key = 'special_offer_end_date'
ORDER BY meta_value DESC LIMIT 1;

Four numbers matter, in order:

  1. Query_time: how long the query took. The headline number.

  2. Rows_examined vs Rows_sent: the ratio. Examining 89,412 rows to return 1 is a textbook missing-index problem.

  3. Lock_time: time spent waiting for a table lock. Anything over 100ms here means your real issue is concurrency (many requests competing), not the query itself.

  4. The query: what work was actually done.

The order to read the log in

This is the order that catches the high-impact problems first.

Step 1: Group by query template, not by individual query

A WordPress slow log can hold 2,000 entries that are really just three queries repeated with different IDs. Reading them one by one wastes hours. Group them with pt-query-digest from the free Percona Toolkit:

pt-query-digest /var/log/mysql/slow.log

This groups queries by template and ranks them by total time spent. The template consuming 60% of total slow-log time is your top target, and it is often something nobody would spot reading raw entries.

Step 2: Look at total time first, not per-query time

The most expensive query is usually the one that runs 5,000 times at 80ms each (400 seconds total), not the one that runs once at 2 seconds. The 2-second query is annoying. The 5,000-times query is your bottleneck. pt-query-digest Sorts by total time by default, so trust that order.

Step 3: Match each top query to a pattern

Almost every heavy query falls into one of five patterns. This table is the quick version; details follow.

Missing index: High rows-examined to rows-sent ratio. Add an index, or query by post_id firstN+1 queriesSame template repeated thousands of times, one row eachBatch the loop into a single query (code change)Autoload lookupswp_options query running many times per requestCache in the object cache, not the databaseTransient cleanupA long DELETE ... LIKE '_transient_%'Clear via WP-CLI, then fix the plugin creating them. WooCommerce sessions: heavy queries on sessions or order meta. HPOS migration, more aggressive session cleanup

Missing index: the query filters on a column without an index. The classic offender is wp_postmeta meta_value. WordPress indexes meta_key but not meta_value, so any value-based filter scans the whole table.

N+1: the same query template appears thousands of times in a short window, each fetching a single row, usually because a theme or plugin runs a lookup inside a loop instead of once.

Autoload lookups: a wp_options lookup runs 50-200 times per request. This is not really a database problem; cache the result instead of repeatedly querying the database.

Transient cleanup: a DELETE against wp_options for expired transients runs for several seconds because a plugin created millions of them. (A transient is WordPress's store for temporary data with an expiry.)

WooCommerce sessions: heavy queries against session or order data during cart activity, usually eased by migrating to HPOS (High-Performance Order Storage) and cleaning sessions more often.

Step 4: Find the code that owns the query

Knowing the query is half the job; knowing which plugin fired it is the other half. Three ways:

  • Query Monitor (free, in development) shows the call stack for every query, which you match to a plugin or theme folder.

  • Query comments: some plugins tag their queries with a comment that shows up in the log, making them easy to trace.

  • An APM like New Relic or Tideways tags every query with the hook and plugin that triggered it, removing the guesswork. Not free, but worth it on a busy production site.

Step 5: Fix the right thing

Most slow-log fixes are not new indexes. In rough order of frequency, they are: batching N+1 lookups into a single query, adding a caching layer (object cache or transient cache), replacing a plugin whose queries cannot be fixed, and only then adding an index when none of the above apply. Adding an index without understanding why a query is slow often just delays the problem, because the same query against a far larger table will be slow regardless.

[INSERT IMAGE HERE using the orange Image button: URL https://boltaudit.com/og-default.svg, alt "Reading a WordPress slow query log entry". Swap the URL for your real thumbnail before publishing.]

Before you change anything: a quick safety note

Reading the log and running EXPLAIN on a query are completely safe. The risky steps are adding indexes and deleting rows, especially on a write-heavy table like wp_postmeta or on a live WooCommerce store where a bad change can interrupt checkout. The rule is simple: back up your database before adding an index or deleting rows. A backup turns a risky change into a reversible one.

What never to do

  • Do not enable the general query log on production. It records every single query and will fill your disk within hours. Only the slow log is safe to leave on.

  • Do not optimize a query with an acceptable rows-examined count. If the row count is reasonable and the query is still slow, the problem is server load, not the query.

  • Do not add indexes without measuring. Every index slows writes, so a wrong index on a busy table costs more than the reads it speeds up.

How BoltAudit reads the slow query log for you

If reading a slow log line by line is not how you want to spend an afternoon, the whole process can be automated.

[Make the word BoltAudit below a link with the chain/link button: https://wordpress.org/plugins/boltaudit/]

BoltAudit is a free, AI-powered WordPress performance audit plugin that runs more than 200 read-only checks across frontend, backend, database, and infrastructure in under 90 seconds. Its backend collector reads your slow query log (when the host exposes it) and automatically applies the same categorization above, returning the top query templates, the pattern each one matches, the WordPress hook that triggered it, and the recommended fix. Read-only means it never writes to your database or deletes anything, so it is safe to run on a live production or WooCommerce site. Audits are located under Tools> BoltAudit in your WordPress admin.

Keep the backend healthy over time

Query performance drifts as tables grow and plugins change. A light habit keeps it in check:

  • Run a diagnostic slow log (0.1s threshold) for an hour after any major plugin or theme change.

  • Recheck monthly, since a query that was fine at 100k rows can become slow at several million rows.

  • Always back up before adding an index or deleting rows.

Run it on your site

If your slow query log has been sitting there waiting for someone to read it, that someone does not have to be you. Install BoltAudit free, run a Local Audit from Tools, then BoltAudit, and let it surface the queries that are actually costing you time, with the fix for each.

Run BoltAudit on your site

Free plugin · 1 site · 3 audits per month · no credit card.

See plans →