Make WordPress Core


Ignore:
Timestamp:
08/25/2022 04:21:40 AM (4 years ago)
Author:
peterwilsoncc
Message:

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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-query.php

    r53891 r53941  
    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
     
    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 ) {
     
    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                }
     
    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;
    3103                         }
    3104 
    3105                         return $r;
     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' );
     3193                        }
     3194
     3195                        return $post_parents;
    31063196                }
    31073197
     
    31453235                                $this->request = apply_filters( 'posts_request_ids', $this->request, $this );
    31463236
    3147                                 $ids = $wpdb->get_col( $this->request );
    3148 
    3149                                 if ( $ids ) {
    3150                                         $this->posts = $ids;
     3237                                $post_ids = $wpdb->get_col( $this->request );
     3238
     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();
     
    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 );
     
    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' );
    3206 
    3207                         $cache_key   = "comment_feed:$key:$last_changed";
    3208                         $comment_ids = wp_cache_get( $cache_key, 'comment' );
     3306                        $comment_key          = md5( $comments_request );
     3307                        $comment_last_changed = wp_cache_get_last_changed( 'comment' );
     3308
     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 );
Note: See TracChangeset for help on using the changeset viewer.