From 92994bd3368b5bb09de95087501bf3b57c377499 Mon Sep 17 00:00:00 2001 From: Jonny Harris Date: Tue, 5 Sep 2023 12:21:27 +0000 Subject: [PATCH] Query: Use split queries in WP_Query if persistent object caching is enabled. Prior to this commit, the `WP_Query` class split the query for posts into two database queries. First, it initiated an ID-based query to retrieve post IDs, followed by a call to _prime_post_caches to fetch post objects if they weren't already in memory. This splitting of queries was limited to cases where fewer than 500 posts were being requested, to prevent a potentially large database query within the IN statement in _prime_post_caches. However, this limitation becomes unnecessary when a persistent object cache is enabled, as the post objects can be efficiently retrieved from the fast object cache. This commit transfers the responsibility of fetching posts to the object cache, which not only speeds up the process but also reduces the strain on the database server. Props peterwilsoncc, spacedmonkey, SergeyBiryukov. Fixes #57296. git-svn-id: https://develop.svn.wordpress.org/trunk@56513 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-query.php | 9 ++++++++- tests/phpunit/tests/post/nav-menu.php | 10 +++++----- tests/phpunit/tests/post/query.php | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 0aae0379fe..16e1cfc248 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -3271,7 +3271,14 @@ class WP_Query { } if ( null === $this->posts ) { - $split_the_query = ( $old_request == $this->request && "{$wpdb->posts}.*" === $fields && ! empty( $limits ) && $q['posts_per_page'] < 500 ); + $split_the_query = ( + $old_request == $this->request + && "{$wpdb->posts}.*" === $fields + && ( + wp_using_ext_object_cache() + || ( ! empty( $limits ) && $q['posts_per_page'] < 500 ) + ) + ); /** * Filters whether to split the query. diff --git a/tests/phpunit/tests/post/nav-menu.php b/tests/phpunit/tests/post/nav-menu.php index c0ae716ab8..a9cfe20e41 100644 --- a/tests/phpunit/tests/post/nav-menu.php +++ b/tests/phpunit/tests/post/nav-menu.php @@ -342,13 +342,13 @@ class Tests_Post_Nav_Menu extends WP_UnitTestCase { add_filter( 'update_post_metadata_cache', array( $action, 'filter' ), 10, 2 ); $start_num_queries = get_num_queries(); - wp_get_nav_menu_items( $this->menu_id ); + wp_get_nav_menu_items( $this->menu_id, array( 'nopaging' => false ) ); $queries_made = get_num_queries() - $start_num_queries; - $this->assertSame( 6, $queries_made, 'Only does 6 database queries when running wp_get_nav_menu_items.' ); + $this->assertSame( 7, $queries_made, 'Only does 7 database queries when running wp_get_nav_menu_items.' ); $args = $action->get_args(); $this->assertSameSets( $menu_nav_ids, $args[0][1], '_prime_post_caches() was not executed.' ); - $this->assertSameSets( $post_ids, $args[1][1], '_prime_post_caches() was not executed.' ); + $this->assertSameSets( $post_ids, $args[2][1], '_prime_post_caches() was not executed.' ); } /** @@ -383,10 +383,10 @@ class Tests_Post_Nav_Menu extends WP_UnitTestCase { add_filter( 'update_post_metadata_cache', array( $action_posts, 'filter' ), 10, 2 ); $start_num_queries = get_num_queries(); - wp_get_nav_menu_items( $this->menu_id ); + wp_get_nav_menu_items( $this->menu_id, array( 'nopaging' => false ) ); get_term_meta( $term_ids[0] ); $queries_made = get_num_queries() - $start_num_queries; - $this->assertSame( 6, $queries_made, 'Only does 6 database queries when running wp_get_nav_menu_items.' ); + $this->assertSame( 7, $queries_made, 'Only does 7 database queries when running wp_get_nav_menu_items.' ); $args = $action_terms->get_args(); $first = reset( $args ); diff --git a/tests/phpunit/tests/post/query.php b/tests/phpunit/tests/post/query.php index f5ecd49b05..9c118cbb9e 100644 --- a/tests/phpunit/tests/post/query.php +++ b/tests/phpunit/tests/post/query.php @@ -775,4 +775,21 @@ class Tests_Post_Query extends WP_UnitTestCase { $this->assertIsInt( $q->found_posts ); } + + /** + * @ticket 57296 + * @covers WP_Query::get_posts + */ + public function test_split_the_query_object_cache() { + $filter = new MockAction(); + add_filter( 'split_the_query', array( $filter, 'filter' ) ); + + $q = new WP_Query( + array( + 'posts_per_page' => 501, + ) + ); + + $this->assertSame( (bool) wp_using_ext_object_cache(), $filter->get_args()[0][0] ); + } }