1

I am building a map of posts and taxonomies to do some more intensive processing later on.

Right now I am querying the posts with WP_Query and iterating over each one to get their taxonomy terms and then dump all of that into an array for use later.

I know this isn't right from a performance and "best standards" perspective. I don't want to make database calls in a loop and I would really prefer to eagerly load all post terms on the first query with the posts.

Is this possible? How?

  • Counter-intuitively, that is the best way to do things in WP, as it loads the postmeta data for you, so subsequent get_post_meta() don't do any more database accesses. – bonger Jul 28 '14 at 23:42
  • You can use ` wp_get_post_terms` – Bindiya Patoliya Jul 29 '14 at 5:09
  • I am using wp_get_post_terms but I thought that this causes another DB query. Is that not the case? – Jeff Jul 29 '14 at 14:41
1

According to user Otto, who provides a good explanatory answer to a similar question, you can safely call wp_get_post_terms() a number of times because Wordpress's internal query caching system is primed before the loop begins, and subsequent calls to wp_get_post_terms() will hit the cache rather than the query:

Post meta information is automatically cached in memory for a standard WP_Query (and the main query), unless you specifically tell it not to do so by using the update_post_meta_cache parameter.

Therefore, you should not be writing your own queries for this.

How the meta caching works for normal queries:

If the update_post_meta_cache parameter to the WP_Query is not set to false, then after the posts are retrieved from the DB, then the update_post_caches function will be called, which in turn calls update_postmeta_cache.

The update_postmeta_cache function is a wrapper for update_meta_cache, and it essentially calls a simple SELECT with all the ID's of the posts retrieved. This will have it get all the postmeta, for all the posts in the query, and save that data in the object cache (using wp_cache_add).

However, his explanation didn't provide much by way of code to prove it, nor any actual query analysis of a page. So, just to be sure, I fired up the Query Monitor plugin and ran some tests on my own archive pages. It is showing that I am calling wp_get_object_terms() (always fired by wp_get_post_terms() and the actual query caller) 85 times, which might seem like a high number. However, each call takes ~.0005 seconds. So all told they total to about .05 seconds. My total query time for all 400-500 queries on the page (I am using the somewhat bloated Themify Magazine theme) is 0.36 seconds.

So I guess the lesson is (assuming my bloated theme didn't do something crazy like interrupt WP's internal caching): simple queries run by wp_get_post_terms() are so inconsequential that if you're only firing them off a handful of times, they show scant degradation in performance. However, if you are hungry to optimize, it looks like Wordpress is not priming any cache for this data up front as user Otto has indicated.

| improve this answer | |
  • 400 - 500 queries are insanely high. Everything above 30 are getting high, but 400 is insane. Also, over 1 second is also really bad. You should really take a good look at your setup and check where all these queries are coming from – Pieter Goosen Jan 13 '15 at 16:40
  • Thank you @PieterGoosen. I actually clarified the post as I had a number of points wrong! Using another plugin, I got a more granular look at the queries and found that, although there are a ton of queries, they are all trivially inexpensive. I had misread the 2 second figure as query time. That was actually total page load time. Also, while it would be good to consolidate these little SELECTs where one can, I am using a pretty bloated theme for its ease-of-use, plus a few snappy caching layers anyhow. I don't see the value in optimizing just yet. – Adam Friedman Jan 13 '15 at 20:12

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.