By the time I decided to optimize some of my WordPress queries to be more efficient I was already using some caching techniques.
Most of my WordPress projects are hosted on my own Google Compute Engine based web-server on Debian. While static content is also delivered from a Cloudflare CDN.
So my normal setup was CDN -> Frontend Nginx -> proxy to Varnish -> Backend Nginx -> fastCGI PHP-fpm
It goes pretty fast on everything for non-logged-in users and performs well for logged-in, as static content is being cached, and varnish and fastcgi cache does a good job on dynamic content for optimized queries.
It turned out, I needed a feature to display random posts. Many articles related to WordPress, cover the topic, stating the usage for random posts:
$args = array( 'orderby' => 'rand', ); query_posts( $args );
However, it’s rarely mentioned, that this query is an expensive one, and gets exponentially slow as the database grows.
WordPress Official Recommendations
I really wanted to display random posts, but didn’t want my sites to slow down, so I digged into the topic, and here is what WordPress itself recommends – WP Object Cache
If you read the article carefully, you will note, that while functions for object caching (query results are objects by the way), they are not active in WordPress by default, and you have to code your own solution or install a plugin.
Besides, you need to wrap your expensive queries into a cache check functions:
$random = wp_cache_get( 'home_random' ); if ( false === $random ) { $random_args = array( 'post_type' => 'post', 'orderby' => 'rand', 'posts_per_page' => $num, 'max_num_pages' => 1 ); $random = new WP_Query( $random_args ); wp_cache_set( 'home_random', $random, '', 86400 ); }
I knew I don’t need those queries to refresh often, so I used wp_cache_set with an expiration time of 86400 seconds (1 day).
Redis, PHP extension for Redis and WordPress plugin for Redis
As for the plugins, I know that industry is well accepting Redis software for caching, so I decided to give the Redis Object Cache plugin a go. However, note that it will only work if you are able to install redis with command line on your webserver, or your hosting provider has it installed for you. I followed this article for installation process.
After installation, you will also need a redis extension for php. For Debian use this in command line:
apt-get update apt-get dist upgrade apt-get install php-redis
Don’t forget to restart PHP after completing these steps!
In my case I have php 7.4 with FPM:
systemctl restart php7.4-fpm
Other recommendations
I had some specific to my usage issues, that you might not really encounter, however, here are some time savers for you:
- If you have multiple domains on your webserver, you need to specify separate Redis database in your wp-config.php for each one. E.g.
define('WP_REDIS_DATABASE', 1);
- In my case I’m also using Nginx rules for FastCGI caching, so I added some rules for random queries:
if ( $query_string ~ "orderby=rand" ) { set $skip_cache 0; } if ($args ~ "orderby=rand") { set $skip_cache 0; }
Did my article help you or am I doing something wrong? Please share your thoughts in comments section!