WordPress Post Editor Performance
Posted on August 17, 2016
WordPress Performance sometimes seems like an endless quest, but there are sometimes little things that come along and yield great rewards.
Front end and back end WordPress Performance auditing and optimizing is a topic I’ve been meaning to write more depth about since speaking on the topic at a few WordPress meetups, but I wanted to quickly share a performance tip on something I came across today while preparing a bug report for Yoast’s WordPress SEO plugin.
Spotting Performance Issues in WordPress
One of the ways we spot performance issues is to run Query Monitor on most of the sites we work on. Query Monitor is a great tool for a quick view into what’s going on on the backend on every page view and I’ll go into more in a future post.
TL:DR; Skip to #3 at the end.
I am no Chris Lema, which is a abstract way of saying, “I personally don’t spend much time in WordPress post editor”. However, today I was in there investigating a little visual glitch with the WordPress SEO snippet preview metabox when I also noticed that the post editor was loading very slowly. Thanks to Query Monitor I could instantly see the cause was a slow MySQL Query and it was coming from a function called meta_form().
Now, this was on a client’s site with over 100,000 posts and with a site that size performance issues show up rather quickly. This however, does affects smaller sites as well though not to the extent it does large publisher websites like this one. Also just to be clear it is really impacted by the number of rows in the postmeta table, not the number of posts directly, but I figured saying 100,000 post made more sense that 1.8 million rows. On the big site like this one though it was causing a 15 second query. While loading the post editor is infrequent, even on a site like this one with over 100 authors, that 15s is taking up a valuable MySQL thread and certainly frustrating authors.
On my much smaller personal blog it was still delaying page load several seconds and here on 9seeds.com (two sites with no where near as big of a database as our typical client’s site) it was causing a 7s slowdown on the post editor loading.
Geeky WordPress Developer Details of the slowdown
WordPress runs a function called meta_form() which displays the custom fields meta box. It runs a somewhat intensive query on the wp_postmeta to generate that box (a box most people don’t even need anymore, but that’s a whole separate issue).
That query looks like this:
SELECT DISTINCT meta_key
FROM wp_postmeta
WHERE meta_key NOT BETWEEN '_'
AND '_z' HAVING meta_key
NOT LIKE '\\_%'
ORDER BY meta_key
LIMIT 30
That’s actually the improved version of the query! When these changes were made to improve the query back in WordPress version 4.3 it seems that only half the needed changes to the database were made for existing sites. The table index was updated to 191 characters, but the field itself was not updated. That mismatch makes that query super slow on large wp_postmeta tables.
There is a new bug report for this performance issue already. While it seems like a trivial thing to fix any time WordPress core needs to modify the existing database on millions of WordPress it’s a pretty big deal and can take a while to get incorporated.
The good news is there are a couple fixes you can implement yourself.
1. (not recommended) My first fix was to truncate the meta_key column to 191 characters with:
ALTER TABLE wp_postmeta MODIFY meta_key varchar(191);
That worked, but it’s a bit dangerous since you could have a very long meta_key and it could get truncated, so don’t do that, there are better ways.
2. (recommended) Much easier, in WordPress 4.4 there was a new filter introduced that short-circuits that query ‘postmeta_form_keys‘ which you can provide a pre-defined array of keys to if you need.
add_filter('postmeta_form_keys', array('my_key1, my_key2');
3. (most recommended) Just ditch loading the ancient custom fields box entirely with:
/**
* Remove Ancient Custom Fields metabox from post editor
* because it uses a very slow query meta_key sort query
* so on sites with large postmeta tables it is super slow
* and is rarely useful anymore on any site
*/
function s9_remove_post_custom_fields_metabox() {
foreach ( get_post_types( '', 'names' ) as $post_type ) {
remove_meta_box( 'postcustom' , $post_type , 'normal' );
}
}
add_action( 'admin_menu' , 's9_remove_post_custom_fields_metabox' );
Added to your theme or a core functionality plugin.
Please do let me know if this helps you in the comments, and stay tuned for a deeper dive into WP site performance auditing and fixes.