Caching in WP_Query with WP 6.1

Starting from WP 6.1, caching for certain database queries has been added to the WordPress core. In particular, caching for WP_Query requests. This has improved the system's performance.

Caching Queries in WP_Query

With WordPress 6.1, database queries implemented in the WP_Query class are cached. Therefore, if the same database query is executed more than once, subsequent results will be loaded from the cache.

If your site uses persistent object caching, database queries will be cached in the object cache and will not be executed until the cache is cleared. All of this reduces the number of database queries on the site as a whole.

If persistent caching is not set up (memory caching is in use), the site will also benefit because repeated queries on the page will not be executed but will be taken from the cache. However, performance improvement will not be as significant in this case.

For Developers

Developers need to ensure that built-in WP functions, such as wp_insert_post(), are used for adding or updating posts. These functions will ensure proper cache invalidation.

If you are updating the database directly, after updating a row in the database, make sure to clear the post cache using the clean_post_cache() function.

How to Disable Caching?

Caching for database queries is now enabled by default in WP_Query.

If you need to disable query caching, set the parameter cache_results=false:

$query = new WP_Query( [
   'posts_per_page' => 50,
   'cache_results'  => false
] );

If you need to globally disable such caching for all queries, use the parse_query filter:

add_action( 'parse_query', 'disable_caching' );
function disable_caching( $wp_query ) {
   $wp_query->query_vars['cache_results'] = false;
}

For better performance, it is strongly recommended to keep caching enabled and clear the cache selectively using the clean_post_cache() function when needed.

Cache Key (How It Is Determined Whether Cache Exists)

Whether a cache exists or not is determined by comparing the cache key.

The cache key is created from the parameters of the query passed to WP_Query{}. 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. The most important parameter to note is fields. This means that if you execute the following:

$query1 = new WP_Query( [
	'posts_per_page' => 50,
	'fields' => 'ids'
] );

$query2 = new WP_Query( [
	'posts_per_page' => 50,
	'fields' => 'all'
] );

In both cases, the query will now request all fields so that the result can be cached and then used regardless of the fields parameter.

Prior to this change, the database query for these two cases was different, but maintaining this would lead to multiple caches for actually subsets of the same data. This means that now the performance improvement when limiting fields to ids will be less than in the previous version of WordPress.

This change also means that the parameters (caches) update_post_meta_cache and update_post_term_cache are always considered.

Now Unnecessary Plugins

It is recommended to disable and remove plugins that add caching functionality to WP_Query. For example:

For more information, see the Trac ticket #22176.

Caching Users in WP_Query

In WordPress 6.1, a new function, update_post_author_caches(), was introduced.

Before version 6.1, multi-author sites required several separate database queries to retrieve author information. This happened because user data was loaded during the loop.

Now, instead of loading each user separately, data for all users present in the loop is loaded in one query at the beginning of the loop - see update_post_author_caches(). This results in significantly fewer database queries.

Calls to update_post_author_caches() have also been added in other key places in the core code. This has increased performance.

For more information, see the Trac ticket #55716

Caching Related Objects for Menu Items

A new function update_menu_item_cache() has been added to the core. It takes an array of post objects and caches the post or term objects that menu items refer to.

A new parameter update_menu_item_cache has been added for WP_Query. If set to true, it will call update_menu_item_cache(), allowing you to cache menu items in two database queries (one for posts and one for terms).

For more information, see the Trac ticket #55620

--

Source