WordPress Slow Queries: Find and Fix Them
Database queries are the heartbeat of WordPress. Every page load sends queries to MySQL. But hidden among those queries are often the culprits killing your site’s performance: slow queries. This guide shows you exactly how to identify them, understand why they’re slow, and fix them permanently.
What Counts as a Slow Query?
MySQL’s default slow query threshold is 10 seconds. That’s far too generous. Here’s what actually matters:
- Under 10ms: Generally not a concern
- 10-100ms: Watch these if executed frequently
- 100ms-1s: Definitely slow, needs investigation
- Over 1s: Critical performance killer, fix immediately
The real metric isn’t query time alone — it’s query time x execution count. A query running in 0.05 seconds but executing 10,000 times per day contributes 500 seconds of total database load.
Enabling the MySQL Slow Query Log
MySQL Configuration
[mysqld]
slow_query_log = 1
long_query_time = 0.5
log_slow_admin_statements = 1
log_queries_not_using_indexes = 1
slow_query_log_file = /var/log/mysql/slow-query.log
slow_query_log = 1— Enables logginglong_query_time = 0.5— Logs queries over 0.5s (adjust to 0.1 for aggressive logging)log_queries_not_using_indexes = 1— Critical: catches queries without indexes even if fast
MariaDB Configuration
[mysqld]
slow_query_log = 1
long_query_time = 0.5
log_slow_admin_statements = 1
log_queries_not_using_indexes = 1
log_slow_verbosity = query_plan,explain
slow_query_log_file = /var/log/mysql/slow-query.log
The log_slow_verbosity = query_plan,explain is MariaDB-specific and gives you EXPLAIN output automatically in the log.
Reading Slow Query Log Output
# Time: 2026-02-06T14:23:45.123456Z
# User@Host: wordpress_user@localhost
# Query_time: 0.587293 Lock_time: 0.000042 Rows_sent: 1 Rows_examined: 150847
SELECT wp_posts.ID, wp_posts.post_title
FROM wp_posts
WHERE post_content LIKE '%example%'
AND post_status = 'publish'
AND post_type = 'post';
Key metadata:
- Query_time: How long the query took (0.587s = 587ms)
- Lock_time: Time waiting for locks (0 = no contention)
- Rows_sent: Rows returned (1)
- Rows_examined: Rows MySQL scanned (150,847)
In this example, MySQL scanned 150,847 rows to return 1 result. That’s terrible efficiency and a clear sign this query needs an index.
Using EXPLAIN to Understand Queries
EXPLAIN SELECT wp_posts.ID, wp_posts.post_title
FROM wp_posts
WHERE post_content LIKE '%example%'
AND post_status = 'publish'
AND post_type = 'post';
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | wp_posts | ALL | NULL | NULL | NULL | NULL | 5438 | Using where |
The type column hierarchy from fastest to slowest:
- system/const: Single row by primary key (excellent)
- eq_ref: One row per outer row (excellent)
- ref: Multiple rows with same indexed value (good)
- range: Rows within a range using index (good)
- index: Full index scan (okay)
- ALL: Full table scan (worst — almost always the problem)
See type = ALL and key = NULL? Full table scan. The query examined all 5,438 posts. On large databases, this becomes catastrophically slow.
Common WordPress Slow Query Patterns
Pattern 1: Postmeta JOINs Without Indexes
SELECT wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
WHERE wp_posts.post_type = 'post'
AND wp_postmeta.meta_key = 'product_color'
AND wp_postmeta.meta_value = 'blue';
Without indexes on wp_postmeta.meta_key and wp_postmeta.meta_value, MySQL scans the entire postmeta table. On WooCommerce sites with millions of product variants, this takes seconds.
Pattern 2: Options Table Full Scans
Unindexed wp_options queries scan every row. With thousands of options on mature sites, this adds up.
Pattern 3: Taxonomy Queries on Large Sites
Sites with thousands of products or large category hierarchies suffer from missing indexes on term_relationships.
Pattern 4: WooCommerce Multi-JOIN Queries
SELECT wp_posts.ID
FROM wp_posts
LEFT JOIN wp_postmeta AS pm1 ON (wp_posts.ID = pm1.post_id AND pm1.meta_key = '_price')
LEFT JOIN wp_postmeta AS pm2 ON (wp_posts.ID = pm2.post_id AND pm2.meta_key = '_stock_status')
WHERE wp_posts.post_type = 'product'
AND wp_posts.post_status = 'publish';
Each additional JOIN without indexes exponentially increases execution time.
Pattern 5: Search Queries with LIKE Wildcards
SELECT * FROM wp_posts
WHERE post_status = 'publish'
AND (post_title LIKE '%search-term%'
OR post_content LIKE '%search-term%')
The leading wildcard %search-term% prevents index usage. MySQL must scan every row.
Adding Database Indexes
Indexes transform slow queries into fast ones. Here are the most important indexes for WordPress:
-- Fix postmeta queries
ALTER TABLE wp_postmeta ADD INDEX meta_key (meta_key);
ALTER TABLE wp_postmeta ADD INDEX post_id_meta_key (post_id, meta_key);
-- Fix taxonomy queries
ALTER TABLE wp_term_relationships ADD INDEX term_taxonomy_id (term_taxonomy_id);
-- Fix post type and status queries
ALTER TABLE wp_posts ADD INDEX post_type_post_status (post_type, post_status);
-- WooCommerce specific compound index
ALTER TABLE wp_postmeta ADD INDEX post_id_meta_key_value (post_id, meta_key, meta_value(10));
Before adding indexes, check what exists:
SHOW INDEXES FROM wp_postmeta;
Don’t add duplicate indexes — that wastes disk space and slows INSERT/UPDATE operations.
Query Optimization Techniques
Full-Text Indexes for Search
ALTER TABLE wp_posts ADD FULLTEXT ft_content (post_content);
SELECT wp_posts.* FROM wp_posts
WHERE MATCH(post_content) AGAINST('keyword' IN BOOLEAN MODE)
AND post_status = 'publish';
Full-text indexes handle search queries 10-100x faster than LIKE on large datasets.
Object Cache for Frequent Queries
Instead of querying the database repeatedly, cache results in memory with Redis or Memcached. A single slow query executed 1,000 times per day becomes 1 database hit with object caching.
Transient Caching for Expensive Queries
$expensive_data = get_transient('my_expensive_query');
if (false === $expensive_data) {
$expensive_data = $wpdb->get_results(
"SELECT * FROM wp_posts
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
WHERE wp_postmeta.meta_key = 'product_color'
AND wp_postmeta.meta_value = 'blue';"
);
// Cache for 12 hours
set_transient('my_expensive_query', $expensive_data, 12 * HOUR_IN_SECONDS);
}
return $expensive_data;
Plugin-Generated Slow Queries
Most slow queries on WordPress sites come from plugins, not core. Query Monitor shows every query and which code triggered it. Use mysqldumpslow for log analysis:
mysqldumpslow -s c -t 10 /var/log/mysql/slow-query.log
This shows the 10 most common slow queries. Copy each query, then search your plugin code to identify the source.
Monitoring Over Time
mysqldumpslow -s t -t 20 /var/log/mysql/slow-query.log > slow-queries-report.txt
Generate weekly reports of the 20 slowest queries by total time. Track these over weeks to catch degradation early.
Automated Slow Query Detection with WP Multi Tool
WP Multi Tool includes an automated slow query detection module that:
- Automatically enables slow query logging with optimal thresholds
- Parses your slow query log every hour
- Identifies top problematic queries by impact (time x frequency)
- Attempts to pinpoint the source plugin using code analysis
- Recommends specific indexes or optimizations
- Alerts you to new slow queries
The Action Plan
- Enable slow query logging with
long_query_time = 0.5 - Let it run for 24-48 hours to capture realistic traffic
- Use mysqldumpslow to find the slowest queries by total time
- Run EXPLAIN on each slow query to understand the execution plan
- Check if relevant indexes exist; if not, add them
- Use Query Monitor to identify the source plugin
- Implement object caching for frequently executed queries
- Re-run analysis to verify improvements
- Set up ongoing monitoring
Database performance is often the most impactful lever. A site with perfectly optimized queries will feel fast regardless of other factors. Start here — find and fix your slowest queries. WP Multi Tool can automate slow query detection and alerting across your sites.
For broader database optimization, see WordPress Database Optimization: Complete Guide. For the full diagnostic framework, read Finding What Makes WordPress Slow.