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.
Thanks So Much. This took our Edit Page Load from 30 seconds down to 1/2 second.
Awesome! Glad it helped!
The change is atomic! We have a WooCommerce store with ~5k products and ~10k orders, and the loading time of an order went from 2.5s to 0.7s. Thank you very much!
To see my edit products process go from 2-3 minutes to now <5 seconds ... Let me say I nearly fell off my chair. I only found this today after adding the debug bar plugin which traced this 14 second long query. Saving posts was also affected causing me endless pain over the past year. Thank you ... I'm shocked such a query even exists.
Thanks! It’s great to know this post is still helping folks after so many years.
Jon Brown, Thanks!!!
You are most welcome!
Thank you so much. You are the only one who made it simple.
thank you. my order pages went from 78 seconds to 6 seconds. thank you
I love you.
Thanks! We love you too.
Many thanks. You're the only one who really helped!
You made my day! Thanks a lot!
We just ran into the issue, and more friction means our processes are bottlenecked severly. Can you please help us know where exactly to paste the code referred at option 3 ? Should we be pasting it to functions.php ? You can see our issue here https://wordpress.org/support/topic/too-many-datadabse-connections-upper-ceiling-mysql/
You can paste this code into functions.php, or into a site specific core functionality plugin. Either will work fine. However, reviewing your thread on .org, this isn’t related to your periodic DB thrashing. That looks more like soemthing caused by a cron job. We see that often on larger and higher traffic site (on smaller sites it happened, just no one notices or cares). Usually the easiest way to identify the culprit is through application monitoring, New Relic, or simpler code profiling that includes profiling Ajax requests and cron jobs. Typically it comes from things like: updating related posts, search indexing, updating gravitar image chance, updating events posts, etc... it really can be lots of things. Reach out through the contact form if you’d like to hire us to investigate.
Holy cow you are the MAN. Thanks so much for this! My edit post times dropped from 10+ seconds to 2 seconds.
Thanks!
Stumbled here after finding that query in Query monitor plugin. Thanks for sharing. Today is going to be a better day thanks to you
8 seconds down to 1.5 !! you're the best! :))
That’s awesome! Thanks for letting me know this is still helping people.
Jon thx man. you made our day.
Thank you so much , you saved my site
2020 and this fix is still needed! Thank you! This took edit product loading page from 20-30s to 0,96s.
If I use custom fields for publishig additional attributes I cannot use this solution. Do you have a different workaround?
Custom fields continue to work, they're just not accessible in the WP Post Editor screen. If that's how your editing (that's how we did it 15 years ago), I'd suggest moving to a custom fields metabox solution like Advanced Custom Fields, Carbon Fields or CMB2. Modifying your DB table might also help, see the trac ticket referenced above for more info on that, but be aware that that is a very advanced solution, might not work, and might damage your database. Have a backup and test!
This is also causing a huge delay loading Yoast SEO plugin settings in wp-admin. https://github.com/Yoast/wordpress-seo/issues/12894 The ticket to resolve this in WordPress core: https://core.trac.wordpress.org/ticket/33885. Sadly, it's 5 years old, with no resolution in sight.
Rather strange that noboy asked that, but why solution #1 and solution #2 are the same? Am I missing something?
Glad to see someone actually read the whole thing and good catch! I've fixed that, thanks for pointing it out! In short when we updated this very old post from TinyMCE to Gutenberg blocks we messed up copy/pasting that code snippet into a new code block. Blindly altering the table via MySQL is the worst way to fix the underlying problem, but it's still useful history to know for those learning about these types of things.
Hi, I'm not very experienced. can this code also fit inside the Akismet plugin? For example, inside the akismet.php file of the plugin?
Hi Luca - no, this needs to be put in a custom functionality plugin, or your themes functions.php file. Definitely don't go modifying plugins like Akismet which will update and wipe out your changes.
Unfortunately it doesn't work. I pasted this code 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' ); into the first line of the function.php file of the theme I use. In the administration panel at the top I get written. Something is incorrect. I have an e-commerce site and I use woocommerce. When I try to manage the products, the site is very slow and the server cpu reaches 100% of use. I can't solve this slowdown problem.
Where should I add this code in the site please?
The tweak outlined in #3 can be applied either to your theme (functions.php) or a site specific core functionality plugin. Note, this is a very old post and while still relevant to the old visual post editor, would not do anything useful for the newer Gutenberg editor.
Did you look at slow query with Query Monitor plugin? Also it may be just hardware related problem... (1/2cpu only hosting) or bad mysql configuration... or bad / absent cache configuration issues etc etc... There is never be silver bullet for all performance cases...
For this yes, that query will show up in Query Monitor
Thank you very much! The duplicated Query Problem is now gone. Thanks a LOT! Roland
Thank you so much, Mr Jon Brown
Thanks for the snippet (#3)! It actually helped a lot! I do have an issue though, when the snippet is enabled, my custom meta boxes (not the WP default ones) can't be erased. They can save a new value and be updated, but I cannot erase a value from them. Any idea why this would happen?
I haven't seen that behavior. Custom meta boxes (ACF/CMB etc) all should keep working.
Thanks for the snippet (#3)! It actually helped a lot! I do have an issue though. At first, I was thinking it was a searchcrawler bot that was disturbing our site until I figured it was the editor page. I can now sleep well this week
#3 helped but not for long, after recent update i have to very slow queries SELECT meta_id FROM olinp_postmeta WHERE meta_key = '_edit_lock' AND post_id = 25994 UPDATE `olinp_postmeta` SET `meta_value` = '1626817995:1' WHERE `post_id` = 25994 AND `meta_key` = '_edit_lock' 7 and 13 seconds each can u help me with this problem?
The code in this post won't help with those queries. There is no obvious reason those edit lock queries would be slow.
But they are slow, I wrote that the processing takes from 10 to 20 seconds. This happens when I open an order in woocommers. Any ideas? But when I remove the code from the third point, slow requests from this topic are returned.
Dude... you rock I was in pain for months about this issue Thanks a lot
Hi Jon! I want to say thanks a lot for sharing your experience and knowledge. I tried the third solution and it worked for me. Thank you again!
Fantastic : order page loading time was 5,67 sec now its 1,40 sec :) Tks a lot !!
Glad this is still helping folks out!
Hello sir !! may I Say this MAN TO MAN: I LOVE YOU !!!! I had this problem for almost 2 years and couldn't find anything to fix it now it loads time is like 1 second !! previously was 37 !!!! :))))) I can't believe it, man, seriously GOD BLESS YOU. I'M GRATEFUL FOR THE REST OF MY DAYS !!
Glad to hear this is still helping folks after so many years! Thank you for the kind words.
Hi thank you I did the first step that you don't recommend and now it's more fast but I got error 502 when I publish a post. How can I come back ? What was the "meta_key" original value ? Thank you
Not working for me i have added the code in my function.php theme and tried to open some articles to edit but the cpu still load high and the site become slow. please help me ! please what does mean the "s9" in the code ? should i change it ?
It was wonderful! Thanks for sharing this solution.
This is awesome. It was making page creation very slow. Thank you Jon Brown.
Thanks for the info. This code speeds everything up but it removes the custom fields under the screen options which I still need. Is there a code I can use which keeps this custom field. The following code restores the customer fields but the speed of the dashboard is slow. /** * 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' ); } }
You can try the options #1 or #2 described in the post. Those will improve things somewhat without compltely removing the metabox, but pay attention to the warnings about them.
from 99s to 3s.. Thanks man !!