1

In the get_posts method of WP_Query, there's a section relating to split_the_query

The logic of split_the_query is

$split_the_query = ( $old_request == $this->request && "$wpdb->posts.*" == $fields && !empty( $limits ) && $q['posts_per_page'] < 500 );

Which can be summarised as.

If:

  • The calculated query hasn't been modified ($old_request == $this->request)
  • And we're just loading posts ("$wpdb->posts.*" == $fields)
  • And we've set a limit (!empty( $limits ))
  • And that limit is less than 500 rows ($q['posts_per_page'] < 500)

Then it triggers this bizarre alternative way to load content.

*Edit: * Maybe bizarre is a harsh word, I'm sure there's a purpose, it seems to update some caches in the process :)

It's causing issues with one of my custom post types as it also triggers some weird caching mechanism and I run out of memory.

I'm aware I can overwrite it with a hook but I'm wondering what the purpose of it is?

Doesn't seem to be documented. It also seems odd to randomly do it for less than 500 rows.

1 Answer 1

2

It is all for adding posts into the cache. The usefulness of this is so that get_post( $post_id ) doesn't result in another hit to the database. This is likely as many of the template functions inside the loop call get_post().

I don't fully understand the logic for expression for $split_the_query. The limit makes sense as a large limit is probably some batch processes instead being displayed by the theme.

The following code is conditional logic:

if ( $split_the_query ) {
        // First get the IDs and then fill in the objects

        $this->request = "SELECT $found_rows $distinct $wpdb->posts.ID FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";

        $this->request = apply_filters( 'posts_request_ids', $this->request, $this );

        $ids = $wpdb->get_col( $this->request );

        if ( $ids ) {
            $this->posts = $ids;
            $this->set_found_posts( $q, $limits );
            _prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] );
        } else {
            $this->posts = array();
        }
    } else {
        $this->posts = $wpdb->get_results( $this->request );
        $this->set_found_posts( $q, $limits );
    }

$ids = $wpdb->get_col( $this->request ); This gets us an array of the IDs that were returned by the call.

if ( $ids ) If this is false, then no posts returned so just set the posts to an empty array.

_prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] ); This tells WordPress cache to capture the new post IDs for the cache. You'll notice you have two query parameters you can pass in the query associated array to tell which caches to update.

It is weird that a custom post type would cause an issue while the default post post type would give you no issue. You may just want to set the two query vars to false to prevent caching.

It does look like other people are having your issue when I do a Google search for update_post_caches out of memory.

3
  • The memory happens in a sub query, and there's some amount of meta data associated with the custom type so that makes sense..
    – Ben
    Commented Jan 31, 2014 at 5:58
  • The funny thing is the error only started happening because I reduced my page size to < 500 to try reducing the memory usage - but that alternative code uses more memory because of the caching involved.. o.O
    – Ben
    Commented Jan 31, 2014 at 5:59
  • Caching uses more memory. With memory becoming cheaper and cheaper, it is a strategy of leveraging the memory to speed up performance. Commented Feb 1, 2014 at 4:45

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.