Adding caching to database queries in WP_Query
WordPress 6.1 includes an improvement to how database queries are performed in the WP_Query
class, resulting in database queries will be cached. This means that if the same database query is run more than once, the result will be loaded from cache. For those using persistent object caching, this will mean that the database query will not run again until caches are invalidated, resulting in far fewer queries to the database. Sites using in-memory caching will also see the benefit of not repeating these queries, though the performance improvement will not be as significant.
For those doing custom development, please ensure that you are using core Core is the set of software required to run WordPress. The Core Development Team builds WordPress. functions such as wp_insert_post
to add posts to the database. These functions are well-maintained, and by using them, you ensure that caches are correctly invalidated. If you are updating the database directly, then it is strongly recommended that you call the clean_post_cache
function after updating the database row.
It is worth noting that by default, all calls to WP_Query
will be cached going forward. It is possible to opt out of caching queries by simply passing the cache_results
parameter as false
. See example:
$args = array(
'posts_per_page' => 50,
'cache_results' => false
);
$query = new WP_Query( $args );
It is also possible to globally disable caching, using a filter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.:
function disable_caching( $wp_query ) {
$wp_query->query_vars['cache_results'] = false;
}
add_action( 'parse_query', 'disable_caching' );
Disabling caching like this should only be done in extreme cases. For best performance, it is highly recommended to keep caching enabled and invalidate caches using the clean_post_cache
function.
Cache keys are generated using the parameters passed to the WP_Query
class instance. However, the following parameters are ignored:
suppress_filters
cache_results
fields
update_post_meta_cache
update_post_term_cache
update_menu_item_cache
lazy_load_term_meta
These parameters do not affect the database query that is run. The most important ignored parameter is fields
. This means that if you run the following:
$args1 = array(
'posts_per_page' => 50,
'fields' => 'ids'
);
$query1 = new WP_Query( $args1 );
$args2 = array(
'posts_per_page' => 50,
'fields' => 'all'
);
$query2 = new WP_Query( $args2 );
In both cases, the query will now request all fields, so that the result can be cached and then be used regardless of the fields
parameter. Prior to this change, the database query for those two was different, but keeping it like that would have resulted in multiple caches for effectively subsets of the same data. This means that there is now less of a performance improvement when limiting fields
ids than there was in the previous version of WordPress.
This change also means that the update_post_meta_cache
and update_post_term_cache
caches are always respected.
In cases where caching was added to WP_Query
by using plugins such as advanced-post-cache, Enhanced Post Cache or Cache WP_Query, it is recommended that these plugins are disabled and removed as they are no longer required.
For more info, see Trac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. ticket Created for both bug reports and feature development on the bug tracker. #22176
Prime users cache in WP_Query
WordPress 6.1 introduces a new function, update_post_author_caches
. Prior to 6.1, sites with multiple authors required several single database queries to get author information, as the user is loaded as part of the loop The Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop.. Instead of loading each user one by one, user (author) caches are now primed in a single database call by calling update_post_author_caches
at the start of the loop, resulting in far fewer database queries.
This function accepts an array of post objects and will prime user caches. Calls to update_post_author_caches
have also been added in key parts of the codebase to improve database performance.
For more info, see Trac ticket #55716
Prime linked objects for menu items
A new function has been added to core called update_menu_item_cache
. It accepts an array of post objects and will prime caches for post or terms referenced in a menu item. A new parameter for WP_Query
has been added called update_menu_item_cache
. When set to true
it will call update_menu_item_cache
which will allow you to prime menu items in a two database queries (one for posts and one for terms).
For more info, see Trac ticket #55620
get_page_by_title
now uses WP_Query
The function get_page_by_title
now uses WP_Query
. Previously, this function used a raw database query to get the page by title. As noted above, WP_Query
is now cached, meaning that calls to get_page_by_title
will also be cached. This also has the benefit of running through all the filters in WP_Query
.
For more info, see Trac ticket #36905
Thanks to @flixos90, @milana_cap, @peterwilsoncc for peer review and @mxbclang for proofreading.
#6-1, #dev-notes, #dev-notes-6-1, #performance