Database performance issues are relatively common on mid-to-large sized WordPress websites. A very slow loading WordPress admin area, or slow page response times for uncached page requests are the most common symptoms.
If your WordPress site is very slow when editing content admin area then you might have slow SQL queries. You may also have other issues, like slow third-party HTTP/API requests.
There are many things that can cause a slow WordPress website, and just about all of them are covered elsewhere in detail. This article doesn’t focus on the standard front-end advice. If you’re optimizing to improve Search Console issues, then this isn’t for you. It’s for WordPress sites with very slow response times, or your admin area takes more than 3 or 4 secs to load each page.
The following scenarios make your WordPress website much more likely to suffer from slow database queries:
Slow HTTP requests to third-party URL’s is also a common culprit, especially if your site has a large number of premium plugins active. Premium plugins make API requests to external servers that verify the validity of your license keys. When a premium plugin is popular, these license check servers can get overburdened with traffic, I’ve seen it a few times. When this happens, the response times returned slow down, and sometimes take 3 or more seconds each to complete.
When I work on a WordPress websites with SQL query problems, I always start by narrowing down which SQL queries are taking a long time to complete. To do this, I use the Query Monitor plugin’s Database Queries reports. This plugin is my #1 choice for debugging and diagnosing issues with a WordPress site. It provides everything you’ll need in 95% of situations, with the other 5% sometimes warrant specialized tools.
Using this plugin, you can sort your SQL queries by query time to quickly find any that are slowing down your site. Slow queries are typically split into two categories:
If the query is the problem, then you’ll need to optimize it (if possible) to improve its performance, ultimately making it run faster. The MySQL EXPLAIN
statement is very useful for doing this. The EXPLAIN
statement in MySQL provides information about how MySQL executes a query to help you understand and optimize it.
To use EXPLAIN
with a SQL query, all you need to do is add EXPLAIN
to the beginning of the slow query. Once you do this, re-run the query, and you’ll see a table of results with details about the query.
The output returned will probably be confusing at first. Here’s an explanation of what’s going on in the rows returned by EXPLAIN
:
id
– A unique identifier for each select query in the query.select_type
– The type of SELECT (simple, primary, derived, etc.).table
– The table referred to by the row.partitions
– The partitions from which the data is selected, if applicable.type
– The join type. Important types include ALL (full table scan), index (index scan), range (indexed range scan), etc.possible_keys
– Shows which indices MySQL can choose from to find the rows in this table.key
– The index MySQL actually decided to use.key_len
– The length of the key used.ref
– Shows which columns or constants are compared to the index named in the key column to select rows.rows
– The number of rows MySQL believes it must examine to execute the query.filtered
– Percentage of rows filtered by the table condition.Optional extras may be included to provide additional details, such as whether MySQL is using an index, if a temporary table is used, etc. Use the results of the EXPLAIN
query to modify the slow WordPress queries. If they’re part of a plugin or theme that’s not custom, you’ll want to use the query
filter hook to safely make changes to the SQL query.
Next you’ll want to look at your database tables, and more specifically the rows within them, to find large values that may slow down queries.
This query will provide a list of database tables ordered from largest to smallest:
SELECT
table_name as "Table",
table_rows as "Rows",
data_length as "Length",
index_length as "Index",
ROUND(((data_length + index_length) / 1024 / 1024),2) as "Size (mb)"
FROM information_schema.TABLES
WHERE table_schema = database()
ORDER BY `Size (mb)` DESC
The largest table are generally the tables causing issues with query performance (but not always). This query helps you find them.
This query will return the 100 largest rows in the database table used to store custom fields, wp_post_meta
. If your installation uses a prefix other than wp_
you’ll need to adjust this.
SELECT
meta_key,
post_id,
(LENGTH(meta_value) / 1024 / 1024) as raw_size,
CONCAT(ROUND((LENGTH(meta_value) / 1024 / 1024),2), 'mb') as size
FROM wp_postmeta
ORDER BY raw_size DESC
LIMIT 100
Similar to the query that finds large custom fields, this will provide you with the 100 largest posts in your wp_posts
table. This is where post, page and custom post type content is stored in the database. The Gutenberg editor’s JSON structure is stored here as well.
SELECT
ID as post_id,
post_title,
(LENGTH(post_content) / 1024) as raw_size,
CONCAT(ROUND((LENGTH(post_content) / 1024),2), 'kb') as size
FROM wp_posts
ORDER BY raw_size DESC
This query finds the total amount of storage used by specific custom fields. You’ll need to modify the LIKE
clause by replacing team__%
with a rule that matches your custom field key.
SELECT CONCAT(ROUND(SUM(LENGTH(meta_value) / 1024 / 1024), 2), 'mb') as total
FROM wp_postmeta
WHERE meta_key LIKE 'team__%'
For advanced situations, it can be beneficial to add INDEXES
for situations where you want to find rows with specific column values quickly. This is an advanced method, though, and it can potentially cause issues if not used properly.
There are situations where adding an INDEX
for a database column can decrease performance, so it’s important to fully understand how they work before working with them. Indexes will speed up the querying of rows but use additional writes and more storage space. Generally speaking, indexes can improve the speed of SELECT
queries but may slow down INSERT
, DELETE
, and UPDATE
operations.
If you’re unsure of the best ways to add indexes, then I’d recommend starting with the Index WP MySQL For Speed plugin. It allows you to easily add generalized indexes to various tables in your WordPress database and can speed up performance in many cases. If it causes slower queries, then you can revert those changes easily as well.
Proper use of an INDEX
in SQL is highly situational, it depends on factors that vary from one WordPress site to another. If you have business impacting issues with MySQL queries, then I’d suggest working with a professional WP developer with solid database design skills. They’ll be able to analyze your WordPress database and determine the ideal indexes for your site.
The only way to truly improve slow SQL queries in a WordPress database is to analyze the data in the database, optimize the problem areas, and add specific indexes where necessary. Unfortunately, there really isn’t a one-size-fits-all approach that will magically resolve slow query issues for you. Finding the problem and fixing it is and always will be the best approach.