Disable WordPress Core’s term cache priming
A feature of WordPress Core that primes the term and/or meta caches after certain queries can result in performance issues and much longer than normal transaction times.
Note
This feature was deprecated in the release of WordPress versions 6.3.
If you notice slow traces (in New Relic, for example) that have a fairly long-running update_term_cache
, update_termmeta_cache
, or wp_queue_posts_for_term_meta_lazyload
function call, there may be an opportunity to optimize the related query. These issues may also become noticeable when using Query Monitor – you may see a lot of wp_cache_add
or wp_cache_set
calls.
How term cache priming works
Within the WordPress classes WP_Query and WP_Term_Query, there is a post-query step that iterates through the results and adds data to certain caches. The purpose is to save that query data for use in the loop, or in later function calls to get the terms or post metadata, in an effort to reduce database requests.
However, this cache priming is sometimes unnecessary, and if there are a lot of terms, the overhead from updating Memcached can add up.
WP_Term_Query cache priming
For WP_Term_Query, you may see a call to update_term_cache
or update_termmeta_cache
take several seconds. Here’s a New Relic trace:
The significant problem with that trace is the number of calls to Memcached, most of which may not be necessary for the task at hand.
WP_Query cache priming
For WP_Query, you may see similar traces, with the function wp_queue_posts_for_term_meta_lazyload
instead.
Any or all of these may be unnecessary, depending on what the code is doing with the terms that were fetched. Sometimes you may not be using the post meta or terms following a query. If you review the related code that runs after the query, and find the cache priming to be unnecessary, or to be slowing down the request, it’s possible to disable these behaviors on an individual query basis.
Typically, these cache priming actions are not needed for most API requests.
How to disable cache priming selectively
The cache priming is a default setting that can be controlled by query arguments. The source code and documentation for these classes is helpful in understanding where and how these priming activities happen.
Resolving WP_Query priming
For WP_Query, there are two query arguments that default to true, and can be set to false:
update_post_meta_cache
caches the post metadataupdate_post_term_cache
caches the post terms
Here’s a portion of the source code for WP_Query::get_posts
:
if ( $q['lazy_load_term_meta'] ) {
wp_queue_posts_for_term_meta_lazyload( $this->posts );
}
lazy_load_term_meta
is set by the argument update_post_term_cache
earlier in the same method:
if ( ! isset( $q['update_post_term_cache'] ) ) {
$q['update_post_term_cache'] = true;
}
if ( ! isset( $q['lazy_load_term_meta'] ) ) {
$q['lazy_load_term_meta'] = $q['update_post_term_cache'];
}
if ( ! isset( $q['update_post_meta_cache'] ) ) {
$q['update_post_meta_cache'] = true;
}
When using WP_Query, this can be set directly in the argument list or via pre_get_posts
actions.
$args = array(
'posts_per_page' => 10,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
);
$query = new WP_Query( $args );
Resolving WP_Term_Query priming
For WP_Term_Query, there’s one argument that defaults to true and can be set to false:
update_term_meta_cache
caches the term meta (viaupdate_termmeta_cache
)
Also for WP_Term_Query, the update_term_cache
function can be avoided when the fields
query attribute is not set to all
or all_with_object_id
. If only the id and/or slug is needed, then specifying that in the arguments will avoid caching the terms.
Here’s a portion of the source code for WP_Term_Query::get_terms
:
$terms = $wpdb->get_results( $this->request );
if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
update_term_cache( $terms );
}
// Prime termmeta cache.
if ( $args['update_term_meta_cache'] ) {
$term_ids = wp_list_pluck( $terms, 'term_id' );
update_termmeta_cache( $term_ids );
}
To resolve any update_term_cache
issues, review the list of possible fields
parameters and determine if only term slugs or ids are needed instead of the default all
. For example, per the documentation, ‘id=>name’ Returns an associative array of term names, keyed by term ID.
To resolve excessive time spent in update_termmeta_cache
, disable it by setting update_term_meta_cache
to false
.
For example:
// get a list of category names (and their IDs)
$args = array(
'fields' => 'id=>name',
'taxonomy' => array( 'category' ),
'order' => 'ASC',
'orderby' => 'name',
'update_term_meta_cache' => false,
);
$query = new WP_Term_Query( $args );
Note that typically, you’ll only need to disable these cache priming functions when you observe that they are affecting the response time of certain transactions, and they are unnecessary to that transaction.
Last updated: August 08, 2024