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

Was it helpful?

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top