post loop causes wp_users and wp_usermeta DB queries for each users

Whilst WordPress has gotten pretty good at db caching for loops (thumbnails, post meta, terms), it does not pre-emptively cache users (authors).

So if you have 5 different authors across all the posts in your loop, that’s 10 queries (1 for the user object, 1 for the user’s meta cache stash). It’s thanks to WP_Query::setup_postdata() (which is called by the_post()) – this line:

$authordata = get_userdata($post->post_author);

If the post author is already in the cache, no db hit, which is why you could have 100’s of posts in your loop from 5 authors and you’d still only end up with 10 additional queries.

To pre-emptively cache all users in the loop and only ever have 2 queries, no matter how many different authors:

function wpse_203912_the_posts( $posts, $wp_query ) {
    if ( $wp_query->is_main_query() ) { // Remove this condition if you want to cache users whenever anywhere queries posts
        $user_ids = wp_list_pluck( $posts, 'post_author' );
        cache_users( $user_ids );
    }

    return $posts;
}

add_filter( 'the_posts', 'wpse_203912_the_posts', 10, 2 );

The great thing about cache_users() is that it will only hit the db for uncached users, so it’s safe to repeatedly call it without worrying if you’ve already cached the user.

Leave a Comment