Make WordPress Core


Ignore:
Timestamp:
08/25/2022 04:21:40 AM (2 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.