How to solve suspected memory issue in custom WordPress loop?

There are approx. 10,000 items returned by the query.

That’s your problem right there. No matter what you do inside the loop, WordPress is still loading 10,000 post objects into memory.

Batch it up and sprinkle a little magic in your query arguments:

$args = array(
    'fields'         => 'ids', // MAGIC! Just get an array of id's, no objects committed to memory
    'posts_per_page' => 500,   // Batch size: big enough to reduce meta queries, small enough not to hammer memory
    'post_type'      => 'shop_order',
    'post_status'    => 'publish',
    'tax_query'      => array(
        array(
            'taxonomy' => 'shop_order_status',
            'field' => 'slug',
            'terms' => array( 'processing', 'completed', 'cancelled', 'failed', 'refunded' ),
        )
    )
);

$query = new WP_Query;
$paged = 1;
$count = 0;
$total = null;

do {
    $args['no_found_rows'] = isset( $total ); // No need to SQL_CALC_FOUND_ROWS on subsequent iterations
    $args['paged'] = $paged++;

    $post_ids = $query->query( $args );
    update_postmeta_cache( $post_ids ); // Get all meta for this group of posts

    if ( ! isset( $total ) )
        $total = $query->found_posts;

    $count += $query->post_count;

    foreach ( $post_ids as $post_id ) {
        $source = get_post_meta( $post_id, 'Where did you hear about us', true );

        // Do your stuff here



        // Wipe this post's meta from memory
        wp_cache_delete( $post_id, 'post_meta' );
    }

} while ( $count < $total );

Leave a Comment