Skip to content

Commit 7f7d616

Browse files
committed
Query: Cache post ID database query within WP_Query.
Add object caching to the first database query in `WP_Query`, ie the database query for post IDs that match the desired result. Randomly ordered queries remain uncached as they are not intended to return consistent results. Caching of ID queries is enabled by default, per the post object, term and meta caches. Props spacedmonkey, aaroncampbell, batmoo, chriscct7, costdev, dd32, drewapicture, johnbillion, mukesh27, nacin, ocean90, peterwilsoncc, ryan, scribu, sergeybiryukov, tillkruss. Fixes #22176. git-svn-id: https://develop.svn.wordpress.org/trunk@53941 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 193406a commit 7f7d616

3 files changed

Lines changed: 1017 additions & 17 deletions

File tree

src/wp-includes/class-wp-query.php

Lines changed: 119 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,11 +1874,7 @@ public function get_posts() {
18741874
}
18751875

18761876
if ( ! isset( $q['cache_results'] ) ) {
1877-
if ( wp_using_ext_object_cache() ) {
1878-
$q['cache_results'] = false;
1879-
} else {
1880-
$q['cache_results'] = true;
1881-
}
1877+
$q['cache_results'] = true;
18821878
}
18831879

18841880
if ( ! isset( $q['update_post_term_cache'] ) ) {
@@ -3072,6 +3068,77 @@ public function get_posts() {
30723068
*/
30733069
$this->posts = apply_filters_ref_array( 'posts_pre_query', array( null, &$this ) );
30743070

3071+
/*
3072+
* Ensure the ID database query is able to be cached.
3073+
*
3074+
* Random queries are expected to have unpredictable results and
3075+
* cannot be cached. Note the space before `RAND` in the string
3076+
* search, that to ensure against a collision with another
3077+
* function.
3078+
*/
3079+
$id_query_is_cacheable = ! str_contains( strtoupper( $orderby ), ' RAND(' );
3080+
if ( $q['cache_results'] && $id_query_is_cacheable ) {
3081+
$cache_args = $q;
3082+
3083+
unset(
3084+
$cache_args['suppress_filters'],
3085+
$cache_args['cache_results'],
3086+
$cache_args['fields'],
3087+
$cache_args['update_post_meta_cache'],
3088+
$cache_args['update_post_term_cache'],
3089+
$cache_args['lazy_load_term_meta'],
3090+
$cache_args['update_menu_item_cache']
3091+
);
3092+
3093+
$new_request = str_replace( $fields, "{$wpdb->posts}.*", $this->request );
3094+
$key = md5( serialize( $cache_args ) . $new_request );
3095+
3096+
$last_changed = wp_cache_get_last_changed( 'posts' );
3097+
if ( ! empty( $this->tax_query->queried_terms ) ) {
3098+
$last_changed .= wp_cache_get_last_changed( 'terms' );
3099+
}
3100+
3101+
$cache_key = "wp_query:$key:$last_changed";
3102+
3103+
if ( null === $this->posts ) {
3104+
$cached_results = wp_cache_get( $cache_key, 'posts' );
3105+
3106+
if ( $cached_results ) {
3107+
if ( 'ids' === $q['fields'] ) {
3108+
/** @var int[] */
3109+
$this->posts = array_map( 'intval', $cached_results['posts'] );
3110+
} else {
3111+
_prime_post_caches( $cached_results['posts'], $q['update_post_term_cache'], $q['update_post_meta_cache'] );
3112+
/** @var WP_Post[] */
3113+
$this->posts = array_map( 'get_post', $cached_results['posts'] );
3114+
}
3115+
3116+
$this->post_count = count( $this->posts );
3117+
$this->found_posts = $cached_results['found_posts'];
3118+
$this->max_num_pages = $cached_results['max_num_pages'];
3119+
3120+
if ( 'ids' === $q['fields'] ) {
3121+
return $this->posts;
3122+
} elseif ( 'id=>parent' === $q['fields'] ) {
3123+
/** @var int[] */
3124+
$post_parents = array();
3125+
3126+
foreach ( $this->posts as $key => $post ) {
3127+
$obj = new stdClass();
3128+
$obj->ID = (int) $post->ID;
3129+
$obj->post_parent = (int) $post->post_parent;
3130+
3131+
$this->posts[ $key ] = $obj;
3132+
3133+
$post_parents[ $obj->ID ] = $obj->post_parent;
3134+
}
3135+
3136+
return $post_parents;
3137+
}
3138+
}
3139+
}
3140+
}
3141+
30753142
if ( 'ids' === $q['fields'] ) {
30763143
if ( null === $this->posts ) {
30773144
$this->posts = $wpdb->get_col( $this->request );
@@ -3082,6 +3149,16 @@ public function get_posts() {
30823149
$this->post_count = count( $this->posts );
30833150
$this->set_found_posts( $q, $limits );
30843151

3152+
if ( $q['cache_results'] && $id_query_is_cacheable ) {
3153+
$cache_value = array(
3154+
'posts' => $this->posts,
3155+
'found_posts' => $this->found_posts,
3156+
'max_num_pages' => $this->max_num_pages,
3157+
);
3158+
3159+
wp_cache_set( $cache_key, $cache_value, 'posts' );
3160+
}
3161+
30853162
return $this->posts;
30863163
}
30873164

@@ -3094,15 +3171,28 @@ public function get_posts() {
30943171
$this->set_found_posts( $q, $limits );
30953172

30963173
/** @var int[] */
3097-
$r = array();
3174+
$post_parents = array();
3175+
$post_ids = array();
3176+
30983177
foreach ( $this->posts as $key => $post ) {
30993178
$this->posts[ $key ]->ID = (int) $post->ID;
31003179
$this->posts[ $key ]->post_parent = (int) $post->post_parent;
31013180

3102-
$r[ (int) $post->ID ] = (int) $post->post_parent;
3181+
$post_parents[ (int) $post->ID ] = (int) $post->post_parent;
3182+
$post_ids[] = (int) $post->ID;
3183+
}
3184+
3185+
if ( $q['cache_results'] && $id_query_is_cacheable ) {
3186+
$cache_value = array(
3187+
'posts' => $post_ids,
3188+
'found_posts' => $this->found_posts,
3189+
'max_num_pages' => $this->max_num_pages,
3190+
);
3191+
3192+
wp_cache_set( $cache_key, $cache_value, 'posts' );
31033193
}
31043194

3105-
return $r;
3195+
return $post_parents;
31063196
}
31073197

31083198
if ( null === $this->posts ) {
@@ -3144,12 +3234,12 @@ public function get_posts() {
31443234
*/
31453235
$this->request = apply_filters( 'posts_request_ids', $this->request, $this );
31463236

3147-
$ids = $wpdb->get_col( $this->request );
3237+
$post_ids = $wpdb->get_col( $this->request );
31483238

3149-
if ( $ids ) {
3150-
$this->posts = $ids;
3239+
if ( $post_ids ) {
3240+
$this->posts = $post_ids;
31513241
$this->set_found_posts( $q, $limits );
3152-
_prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] );
3242+
_prime_post_caches( $post_ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] );
31533243
} else {
31543244
$this->posts = array();
31553245
}
@@ -3165,6 +3255,18 @@ public function get_posts() {
31653255
$this->posts = array_map( 'get_post', $this->posts );
31663256
}
31673257

3258+
if ( $q['cache_results'] && $id_query_is_cacheable ) {
3259+
$post_ids = wp_list_pluck( $this->posts, 'ID' );
3260+
3261+
$cache_value = array(
3262+
'posts' => $post_ids,
3263+
'found_posts' => $this->found_posts,
3264+
'max_num_pages' => $this->max_num_pages,
3265+
);
3266+
3267+
wp_cache_set( $cache_key, $cache_value, 'posts' );
3268+
}
3269+
31683270
if ( ! empty( $this->posts ) && $q['update_menu_item_cache'] ) {
31693271
update_menu_item_cache( $this->posts );
31703272
}
@@ -3201,14 +3303,14 @@ public function get_posts() {
32013303

32023304
$comments_request = "SELECT {$wpdb->comments}.comment_ID FROM {$wpdb->comments} $cjoin $cwhere $cgroupby $corderby $climits";
32033305

3204-
$key = md5( $comments_request );
3205-
$last_changed = wp_cache_get_last_changed( 'comment' );
3306+
$comment_key = md5( $comments_request );
3307+
$comment_last_changed = wp_cache_get_last_changed( 'comment' );
32063308

3207-
$cache_key = "comment_feed:$key:$last_changed";
3208-
$comment_ids = wp_cache_get( $cache_key, 'comment' );
3309+
$comment_cache_key = "comment_feed:$comment_key:$comment_last_changed";
3310+
$comment_ids = wp_cache_get( $comment_cache_key, 'comment' );
32093311
if ( false === $comment_ids ) {
32103312
$comment_ids = $wpdb->get_col( $comments_request );
3211-
wp_cache_add( $cache_key, $comment_ids, 'comment' );
3313+
wp_cache_add( $comment_cache_key, $comment_ids, 'comment' );
32123314
}
32133315
_prime_comment_caches( $comment_ids, false );
32143316

0 commit comments

Comments
 (0)