36

I was reading over some best practices from 10up and they mention setting these two flags to false in a WP_Query ( depending on what you're querying ):

  • 'update_post_meta_cache' => false: useful when post meta will not be utilized.
  • 'update_post_term_cache' => false: useful when taxonomy terms will not be utilized.

I am assuming it utilizing something like update_post_caches() but I'm not even 100% sure what that means. Could somebody explain what these two flags mean in a WP_Query and how useful they are? The more information the better as I do not know a whole lot about how WordPress caches things but a well thought out answer regarding these two flags is also acceptable.

2 Answers 2

54

Object cache everywhere

WordPress tries to reduce the number of database queries as much as possible.

For example, anytime you get a meta field or a taxonomy field, before querying the database, WordPress looks if that that was already queried and stored in cache, and returns it from there instead of querying the database.

The "cache job" is done via WP_Object_Cache class and wp_cache_* functions (that are wrapper to that class methods.)

Where cache lives

By default, the "cache" is nothing more than a PHP global variable. It means that it is in memory, but also means that it vanishes on every request.

However, via dropins (advanced-cache.php and / or object-cache.php), it is possible to setup a custom way to handle this cache.

Usually, this dropins are used to setup some sort of caching mechanism that "survive" the singular requests.

For this reason, among WP people, these are know as "persistent cache" plugins (even if outside the bubble the words "cache" and "persistent" don't not make a lot of sense together).

Popular choices nowadays are Memcached or Redis.

So using "persistent cache" plugins you can drastically reduce the number of database queries, because the cache is not updated on every request.

Some examples

$foo = get_post_meta('foo', $post_id, true);
// a lot of code in the middle
$bar = get_post_meta('bar', $post_id, true);

The 2 lines of code above will trigger, at maximum, 1 database query.

In fact, when you query a custom field, all the fields for that post are retrieved from database, cached via object cache, and subsequent requests pull data from cache and not from db.

The same happen for taxonomy terms, WordPress pulls all the terms for a taxonomy once, then returns them from cache.

Object cache is used very widely in WordPress. Not only for posts, meta values and taxonomies, but also for users, comments, theme data...

What WP_Query has to do with all of this?

When you query some posts via WP_Query, by default, WordPress not only pulls them from database (or from cache if they are cached) but also updates the cache for all custom fields and all taxonomies related to the posts pulled.

So when you call, for example, get_the_terms() or get_post_meta() while looping posts got via WP_Query, you don't actually trigger any database query, but pull information from cache.

Nice, it isn't?

Well, yes, but it comes with a cost.

The cache update "magic" that WordPress does when pull posts via WP_Query happen in update_meta_cache for meta and in update_object_term_cache for taxonomies.

If you look at the source code of those functions, you'll see that there WordPress performs just one db query in each function, but also does a lot of processing. For example, in update_object_term_cache there are 7 nested foreach... if you have a lot of taxonomies, and the number of posts per page is high, this is not very performant.

About those WP_Query arguments, finally

What 'update_post_meta_cache' and 'update_post_term_cache' do when set to false is to prevent WordPress to update cache for custom fields and taxonomies, respectively.

In that case, the first time a custom field or a taxonomy is queried a database query is triggered, and data are cached.

It worth the trouble?

As usual, the answer is it depends. Most of the times to set those values to false, is a good choice, because it prevents unnecessary processing and database queries if not needed, and cache is updated anyway the first time custom field / taxonomy terms are required.

However, if you are going to call, even once, get_post_meta() during the loop and you are going to call get_the_terms() for all (or most) of the taxonomies supported by posts, then the cache updating is triggered anyway, and there might be no actual benefit on setting those query arguments to false.

5
  • Neat! As always your insight is always appreciated GM. Would transients be considered "persistent cache"? So to go further, during a WP_Query the reason for wp_reset_postdata() is to reset global $post and reset the Object Cache? It sounds like if I did a custom WP_Query it would create a new cached object but resetting it would also have to requery to get the original cache. Or maybe I'm getting too far out in the context of this question.
    – Howdy_McGee
    Jan 27, 2016 at 21:03
  • 1
    @Howdy_McGee Object cache and post object are not related. So wp_reset_postdata() do nothing in the regard of object cache. wp_reset_postdata() only reset global post object, that is yet another global variable, that is never cached... Transients are an hybrid thing: when you have some persistent cache plugin installed, transient use that, but if you have no persistent cache plugin, then transients use database.
    – gmazzap
    Jan 27, 2016 at 21:16
  • Ah, I just latched onto global variable notion and assumed it was the global $post or global $wp_query objects, thanks for the clarification!
    – Howdy_McGee
    Jan 27, 2016 at 21:19
  • 1
    On a sidenote, fields => 'ids' sets both caches to false. I suppose it makes sense that an Object Cache only works on Objects but I thought I would just make a mention :D
    – Howdy_McGee
    Feb 29, 2016 at 20:01
  • I still don't get it, if you leave it to true it always loads it and when to false it loads it when you need it, why would anyone ever need to use true and why would that be the default? that's so weird! Basically from what I got the default options (those trues) are useless! Nov 16, 2022 at 21:55
4

The main point of interest here is the update_post_caches function. It is called after WP_Query got all the posts from the DB. Usually, the reason you want the posts in the first place is to display them which usually means to display the terms and something based on the metadata, therefor WP_Query will also by default query the DB for the meta and term data related to the returned posts and stores it the cache*. This information is not explicitly available in the data returned from WP_Query, but when you will call the relevant APIs to get the term and meta info of a specific post, it will already be available in memory and there will be no need to send a new query to the DB.

This enables wordpress to reduce the overhead related to sending requests to the DB by sending only one request to get the information for all of the posts instead of sending a request per each post.

Right now I can not find any non trivial example of when will you not want the cache to update, but a trivial one might be if you just want a list of the titles of all posts. For that you do not need term or meta data.

*cache - Most important here is the memory based cache in which WP stores almot everything which it gets from the DB even without having any object caching plugin active. Obviously when you do have object caching the information will be stored there as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.