loop through all posts memory error

I have few thousands posts and need to list all of them in the admin. When I used WP_Query to get them all at once I got a memory error. Then I split it into several query calls and it worked just fine with 256 MB limit. Here is the code:

$limit = 200;
$offset = 0;
while (TRUE) {
    $posts = new WP_Query(array(
            'posts_per_page'        => $limit,
            'offset'                => $offset,
            'post_type'     =>  $post_type,
            'orderby'       =>  'title',
            'order'         =>  'ASC',
            'post_status' => array('publish', 'private', 'draft', 'inherit'),
    ));

    if (!$posts->have_posts()) break;

    while($posts->have_posts())
    {
            $posts->the_post();

            # do some echoing with the $post
    }

    $offset += $limit;
} /*(TRUE)*/

So this works just fine on development server. But when moved to production, it throws memory error Allowed memory size of 268435456 bytes exhausted (tried to allocate 64 bytes) ...

Read More

I tried lowering the $limit but it doesn’t help (on dev it actually works just fine with $limit = 500.

What else can I do to force it to release memory?

Related posts

Leave a Reply

2 comments

  1. The posts are still held in memory under WordPress’ cache mechanism (even though you replace $posts on every loop) – delete each one after operating on it:

    # do some echoing with the $post
    
    # wipe post from memory
    wp_cache_delete( $post->ID, 'posts' );
    wp_cache_delete( $post->ID, 'post_meta' );
    

    Pro tip: save some needless queries with no_found_rows => true in your query args.

    And if you’re not using categories/tags in your loop, save even more queries (& memory) with update_post_term_cache => false in your query args.

  2. While the above does reduce memory usage somewhat, on large loops (>2500 posts) you will still see memory usage going up with each loop.

    The following will flush all WordPress caches, making memory usage as small as possible:

    wp_cache_flush();