Using the WordPress Object Cache to Cache Query Results

If you have a query that is taking a long time to load, more often than not that query can be cached for a limited amount of time with WordPress object cache. As a result, your site will load faster (i.e. TTFB will be reduced) and function more efficiently.

Identifying a slow query using the Debug bar from Pressable

Plugins like Query Monitor and the Debug Bar can help you identify slow queries on your site and which PHP functions are executing them. The Pressable Customer Success Team uses the Debug Bar. If you need assistance tracking them down, just let us know.

In the Debug Bar, the source function for a slow query can usually be found by locating the PHP function called just before the WP_Query class in the stacktrace. For example:

Locating the function executing the query in a block of code

In this case, we can see that this query is taking approximately 7 seconds to run. The function that is called just before WP_Query is alg_wc_pvbur_get_invisible_products.

If you have a backup of your site via Jetpack Security Daily, you can download the backup and search for the function on your device: “function alg_wc_pvbur_get_invisible_products”. Alternatively, Pressable’s Customer Success team can help you locate the file containing the function as well.

Once you locate the function, you should see the uncached call to WP_Query:

function alg_wc_pvbur_get_invisible_products( $roles = array() ) {
    $query = new WP_Query( alg_wc_pvbur_get_invisible_products_query_args( $roles ) );
    return $query;

When this function is called, that query will be run every single time, even though it probably doesn’t need to execute on every page load. So, on Pressable, you can use the WordPress Transients API or Object Cache to store the results of this query for a determined amount of time. In turn, this allows the query results to be called from the Object Cache, and the page will load much faster.

Note: On Pressable, as we offer a persistent Object Cache via memcached, the Transients API pushes any calls to set_transient(), to wp_cache_set(), for example. For that reason, this example will use wp_cache_set() instead of set_transient() to be efficient. However, if you ever host your site on a server that doesn’t have a persistent object cache, choosing one or the other will make a difference. Read more about the WordPress Object Cache and Transients API.

Adding a query to the cache isn’t as hard as you might think. Here is how you might add the query above to the cache:

1. function alg_wc_pvbur_get_invisible_products( $roles = array() ) {
2.     $key = serialize($roles);
3.     if ( ! $query = wp_cache_get($key) ) {
4.         $query = new WP_Query( 
  alg_wc_pvbur_get_invisible_products_query_args( $roles ) );
5.         wp_cache_set($key,$query,'',3600);
6.     }
7.     return $query;
8. }

Let’s go through this line-by-line.

On line 1, the function name and its parameters stay the same. So, no changes there.

On line 2, we see our first change. When we store something in the Object Cache, we need a unique key that will allow us to later retrieve the data from the Object Cache. As we don’t know where else this function is being used – it could be used in numerous different parts of the site – the only variable we have is the $roles parameter, which may or may not be passed to the function when it’s called.

By serializing $roles, we get a serialized string that will allow us to uniquely identify the data being retrieved in this function.

On line 3, we check for $key. In plain English, “If this key is not stored in the Object Cache…”

On line 4, we run the query if the $key isn’t in the cache.

On line 5, we use wp_cache_set() to store the data. First, we tell the Object Cache what the key is; then we store the query results; next we specify the cache group, if one applies (leaving it blank ('') is usually fine; and finally, we specify the amount of seconds we want this data to persist in the cache.

On line 7, we return the $query results, which were either retrieved from the WP_Object_Cache or WP_Query classes. If it’s the first time this function is running, then the results will come from the query. The next time it runs – assuming it runs before expiration – the results will come from the Object Cache.

If you cached the query correctly, you should notice the query disappear from the Queries tab in the Debug Bar. It will then show up under the $key, whatever it was defined as, in the Object Cache tab of the Debug bar.