Does a query executed through wpdb class get cached?
Question
I am not sure how WordPress cache the queries. I had the impression that whenever I execute a query through wpdb class, it gets cached. For example, on codex under Select a Row and Select a Var, it says the whole query is cached for later use. And I think which means if more data is requested in another query, partials or full results of which are already in wpdb cache, then those are used and a query doesn't happen(in case of full results already in cache). Am I correct in understanding?
I was trying something and I found that I can't use the cache.
For reference, I was listing the recent comments the current user has made. I used get_comments()
but since it only has post id in the results, I used get_the_title()
inside the loop for displaying them. Obviously this is expensive in terms of query, so I though I can cache the required rows of post table by querying them beforehand so that get_the_title()
does no actual query.
I did something like
$query = implode( ' OR ID = ', $collect_post_ids );
$query = 'SELECT * FROM '.$wpdb->prefix.'posts WHERE ID = '.$query.';';
$wpdb->get_results( $query ); // just cache it
but that didn't help. get_the_title()
is still doing queries. Most likely its me who has misunderstood how WP Cache works. So where I am wrong?
Here is the full code for reference - http://ashfame.pastebin.com/BpxjHiQr
Solution
Nope, doesn't work like that. The database-related caching is minimal and mostly covers using precisely same queries during single page load.
Best way to cache persistently database and/or computationally intensive results is using Transients API to store results for fitting period of time.
OTHER TIPS
The docs suggested that the output from a query was only cached for that specific request - so presumably WordPress is doing a buffered query on MySQL.
In my case, I used the wp_cache_* functions - see http://codex.wordpress.org/Class_Reference/WP_Object_Cache
Example code:
sql = "
SELECT {$wpdb->posts}.* FROM {$wpdb->posts}
LEFT JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)
LEFT JOIN {$wpdb->term_taxonomy} ON ({$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id)
WHERE ({$wpdb->term_taxonomy}.taxonomy = 'category' AND {$wpdb->term_taxonomy}.term_id = 9849 )
AND
{$wpdb->posts}.post_status = 'publish' AND
{$wpdb->posts}.post_type = 'post' ORDER BY {$wpdb->posts}.post_title ASC";
$posts = wp_cache_get(md5($sql), 'somerandomkey');
if($posts === false) {
$posts = $wpdb->get_results($sql, OBJECT);
wp_cache_add(md5($sql), $posts, 'somerandomkey');
}
if(empty($posts)) {
echo "<p>No results found </p>";
}
The solution @GingerDog gave works perfectly, but only does so within a single page refresh. If you want to cache your query result for a session you can use a similar solution with $_SESSION (whereas the Transients API works across sessions and machines).
$sQuery = "SELECT `ID`,`post_name` FROM `wp_posts` WHERE `post_type` = 'attachment' AND `post_name` LIKE 'foobar%'";
$sQueryMD5 = md5($sQuery);
if (isset($_SESSION[$sQueryMD5])){
$aResult = $_SESSION[$sQueryMD5];
} else { // search wp_posts
$aResult = $wpdb->get_results($sQuery, OBJECT);
$_SESSION[$sQueryMD5] = $aResult;
}