
Most WordPress performance issues trace back to database queries. A plugin runs a suboptimal SELECT, your homepage load time jumps from 800ms to 4.2 seconds, and you’re left guessing which of your 23 active plugins is responsible.
MySQL’s slow_query_log is the diagnostic tool that ends the guessing. It records every query that exceeds a time threshold you set—usually one or two seconds. The log tells you exactly which SQL statement ran, how long it took, and which rows it examined.
Here’s how to turn it on, read the output, and use it to fix the query that’s killing your site speed.
Enabling slow_query_log on your WordPress host
Most managed WordPress hosts disable direct my.cnf access, but many expose slow query logging through their dashboard. BigScoots, for example, lets you toggle it on via cPanel’s MySQL configuration panel. If you’re on a VPS or dedicated server, you’ll edit the MySQL config file directly.
Add these lines to /etc/mysql/my.cnf (or /etc/my.cnf depending on your distro):
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 1
The long_query_time value is in seconds. Setting it to 1 captures anything longer than one second. For high-traffic sites, you might start at 2 to reduce noise.
Restart MySQL: sudo systemctl restart mysql
Queries now log to /var/log/mysql/slow-query.log. If the file doesn’t exist, MySQL will create it on the first slow query.
Reading the log: what the output actually means
Open the log file. Each slow query entry looks like this:
# Time: 2026-08-30T14:22:35.442891Z
# User@Host: wpuser[wpuser] @ localhost []
# Query_time: 3.204571 Lock_time: 0.000312 Rows_sent: 1847 Rows_examined: 124503
SELECT * FROM wp_posts WHERE post_status = 'publish' ORDER BY post_date DESC;
Here’s what matters:
- Query_time: Total execution time in seconds. This query took 3.2 seconds.
- Lock_time: Time waiting for table locks. Usually negligible unless you’re running MyISAM tables (you shouldn’t be).
- Rows_sent: How many rows the query returned. Here, 1,847.
- Rows_examined: How many rows MySQL scanned to build that result. Here, 124,503. That’s a 67:1 examination-to-return ratio—terrible efficiency.
The query itself follows. In this case, it’s a broad SELECT * with no LIMIT clause, scanning every published post.
Identifying the plugin or theme responsible
The slow query log shows the SQL, but not which PHP file triggered it. To trace that, enable WordPress’s SAVEQUERIES constant in wp-config.php:
define('SAVEQUERIES', true);
Install the Query Monitor plugin. It cross-references the slow queries with the calling function, showing you the exact plugin or theme file responsible.
In most cases, you’ll find one of three culprits:
- A poorly-coded custom query in a theme’s
functions.php - An analytics or “related posts” plugin running uncached lookups on every page load
- A WooCommerce or membership plugin querying order or user meta without indexes
Once you’ve identified the source, you have three options: optimize the query, cache the result, or replace the plugin.
One non-obvious tip: check Rows_examined even for fast queries
A query might finish in 0.8 seconds—just under your long_query_time threshold—but still examine 200,000 rows to return 12. That’s inefficient, and it will degrade as your database grows.
Manually review your site’s most-used queries with Query Monitor’s “Queries by Component” view, sorted by row examination count. If any query examines more than 10x the rows it returns, add an index or rewrite it.
Run EXPLAIN on the suspect query in phpMyAdmin or the MySQL command line to see which indexes MySQL is using (or ignoring). If the “type” column shows “ALL,” you’re doing a full table scan—add an index on the columns in your WHERE or ORDER BY clause.
Want more infrastructure deep-dives like this? Subscribe to One Two Three Send—every article covers one specific tool, feature, or workflow decision for solo operators running content businesses.
