Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

So, I've run into what looks like a WP RAM usage problem and am looking for a solution.

The only place I'm really having this problem on my site is with a Site Map page that I'm trying to populate, but a solution to this problem could be universally applied and save on RAM usage across an entire site.

Essentially, this Site Map page I have is a list of all posts and pages on my site. The only elements of the $post variable that I need access to on this page are the title and permalink. Unfortunately, the query I'm using returns all posts with all the information in each of their $post variables.

The following is an example of a query I'm using on this Site Map page for a single custom-post-type named "products" with a custom taxonomy of "supplements" and term "all-supplements". My Site Map page has multiple such queries, but for explanatory purposes I'm only including the code for this single query.

 $varArray= array(
      'post_type' => 'products',
      'post_status' => 'publish',
      'supplements' => 'all-supplements',
      'posts_per_page' => -1,
      'orderby' => 'title',
      'order' => 'ASC'
 );
 $myProducts= new WP_Query($varArray);

The large majority of the information saved within the $post variable (for my site, and I'm guessing that this trend is seen for general usage) is found within "the content" The typical RAM usage for my Site Map page is ~140MB (reported by Debug Bar), whereas the usage for any other typical page on my site is 50-60MB. Big difference. Yesterday the Site Map page stopped working (WSOD), and to fix it I had to increase the maximum amount of RAM that WP can use. So I'm increasing overall necessary system resources because of a single page.

Thus, I come to my question.

Is there a pathway/option somewhere within Wordpress that I'm missing that would fetch posts/pages like a normal query, but NOT get the content for retrieved posts?

Or, alternatively, is there some easier way for me to only grab particular elements within a given query (Title/Permaklink/Slug/etc...) instead of getting the whole $post variable shebang?

It seems to me that for many WP applications, the only place that "the content" of a post/page would typically be needed is on that page or post page (obviously there are exceptions here), and that having access to the full content for posts/pages retrieved by query on other pages is simple overkill. If there is a way of avoiding loading up the full content for post list pages, then a significant amount of RAM usage could be saved.

Any help would be appreciated.

share|improve this question
add comment

4 Answers

up vote 8 down vote accepted

You can try a trick with querying post data directly and setting filter field of post objects to sample before passing it to get_permalink() to reduce memory usage.

See get_permalink memory usage issue for detailed reasoning behind it.

share|improve this answer
1  
+1 solid article. I had no idea! –  boscho May 2 '13 at 18:56
    
This solution worked great. Well, after a little wrangling that is. :) I had to figure out how to include my custom taxonomy/term to the query, but this was a huge help. Site Map page now using 70MB of RAM (according to Debug Bar). Thanks for the great pointer. –  Programmer Dan May 2 '13 at 22:54
add comment

You might try adding this to your array:

'nopaging' => true,
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false

It seems pretty self-explanatory, but essentially you're not querying all post variables and just the stuff you need.

share|improve this answer
add comment

Programmer Dan, mah man!

Let's get you started on custom SELECT queries using the $wpdb global. The Codex has a great entry on Displaying Posts using a Custom Select Query. If you make use of setup_postdata() you can loop through the results as though you are sitting in the standard Wordpress loop:

global $wpdb;

$sitemap_query = "
    SELECT $wpdb->posts.ID, $wpdb->posts.post_title, $wpdb->posts.guid
    FROM $wpdb->posts
    WHERE $wpdb->posts.post_status = 'publish' 
    AND $wpdb->posts.post_type IN ('post','supplement','another_post_type')
    ORDER BY $wpdb->posts.post_type, $wpdb->posts.post_title DESC
    ";

$sitemap_nodes = $wpdb->get_results($sitemap_query, OBJECT);

if( $sitemap_nodes ):
    global $post;
    foreach ( $sitemap_nodes as $post ):
        setup_postdata( $post );
        ?>

<!-- //Use standard Wordpress template tags for SELECT'd data within The Loop here -->
    <?php the_title() ?>
    <?php the_permalink() ?>

        <?php
    endforeach;
endif;

This query only pulls the posts' IDs, Titles, and GUIDs (used to determine a post's permalink) while absolutely ignoring everything else. It furthermore orders the results first by post_type then post_title, though you may wish to use multiple queries to separate your post types (theoretically at a small performance hit).

Obviously you may wish to skip out on using setup_postdata() and simply loop through $sitemap_nodes, or fiddle with the query to get the results that you need.

If you do call setup_postdata() and have debug mode activated, the calls will likely be spitting out notices left and right regarding (the deliberately) missing information. You may wish to throw an @ before the function call to suppress them after you have confirmed that your custom query is functioning properly.

But this should get you started! You can refer to the following database diagram (from the Database Description page on the Codex) to locate the fields that you need to query:

Wordpress Database Diagram

EDIT:

The most memory efficient solution is likely one that combines a custom SELECT query with @Rarst's protip :)

share|improve this answer
add comment

WP_Query has a "return fields" paramater that looks like this:

$args = array(
 'fields' => 'ids'
);
$query = new WP_Query( $args );

When used this way, WP_Query only returns the post IDs, not the entire post object. Then you can just use the get_permalink(), get_the_title(), and other assorted WordPress functions to retrieve your content based on the post ID.

share|improve this answer
1  
Note that functions that accept post's ID usually just immediately run get_post() on it to retrieve full data and so completely defeat the purpose of retrieving IDs alone. –  Rarst May 7 '13 at 20:18
1  
Good to know! I was under the impression I was being smart. –  Dalton May 7 '13 at 20:29
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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