8

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

4
  • Maybe Scribu's comment here will shine some light(maybe not). core.trac.wordpress.org/ticket/16336
    – t31os
    Feb 2, 2011 at 18:31
  • Not sure! Sorry couldn't make sense out of it. :/
    – Ashfame
    Feb 2, 2011 at 18:36
  • As a side note: $wpdb->posts is the posts table so you don't have to prepend the prefix to a string.
    – Zack
    Feb 2, 2011 at 21:52
  • ah yes I forgot that we have table names saved too. Thanks :)
    – Ashfame
    Feb 2, 2011 at 22:26

4 Answers 4

9

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.

5
  • Execute the same query twice and it still adds up one to the total query count.
    – Ashfame
    Feb 2, 2011 at 18:35
  • 1
    @Ashfame I am not sure every query is cached, on the contrary it is probably far from it. Again - this might save some query here or there internally, but natively WP has no considerable cache for database queries to rely on. If you are especially concerned about queries there are plugins around that provide more extensive and reliable database caching.
    – Rarst
    Feb 2, 2011 at 18:39
  • Thanks! Plugins for providing caching or letting you debug?
    – Ashfame
    Feb 2, 2011 at 19:15
  • @Ashfame Caching. There are both multi-factor caching plugins and those that focus on database. Depends on your specific needs.
    – Rarst
    Feb 2, 2011 at 19:19
  • Sure! I would like to know more. I will digg in more sometime.
    – Ashfame
    Feb 2, 2011 at 20:10
3

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>";
}
0

Here is a solution using transients which relies on your database.

$query = 'SELECT * FROM '.$wpdb->prefix.'posts WHERE ID = 1;';

// Check for transient. If none, then execute WP_Query
if ( false === ( $posts = get_transient( 'cached_posts' ) ) ) {
    $posts = $wpdb->get_results( $query );

    // Put the results in a transient. Expire after 1 minute.
    set_transient( 'cached_posts', $posts, 60 );
    echo 'request executed and cached for 1 min';
}
var_dump($posts);
-1

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;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.