Make WordPress Core


Ignore:
Timestamp:
09/18/2015 07:27:39 PM (9 years ago)
Author:
boonebgorges
Message:

Split the comment query.

WP_Comment_Query now fetches comments in two stages: (1) a query to get the
IDs of comments matching the query vars, and (2) a query to populate the
objects corresponding to the matched IDs. The two queries are cached
separately, so that sites with persistent object caches will continue to have
complete cache coverage for normal comment queries.

Splitting the query allows our cache strategy to be more modest and precise, as
full comment data is only stored once per comment. It also makes it possible
to introduce logic for paginated threading, which is necessary to address
certain performance problems.

See #8071.
data is only stored once per comment, instead of along with

File:
1 edited

Legend:

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

    r34268 r34310  
    3434     */
    3535    public $meta_query = false;
     36
     37    /**
     38     * Metadata query clauses.
     39     *
     40     * @since 4.4.0
     41     * @access protected
     42     * @var array
     43     */
     44    protected $meta_query_clauses;
    3645
    3746    /**
     
    262271        global $wpdb;
    263272
    264         $groupby = '';
    265 
    266273        $this->parse_query();
    267274
     
    282289        $this->meta_query->parse_query_vars( $this->query_vars );
    283290        if ( ! empty( $this->meta_query->queries ) ) {
    284             $meta_query_clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this );
     291            $this->meta_query_clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this );
    285292        }
    286293
     
    292299            wp_cache_set( 'last_changed', $last_changed, 'comment' );
    293300        }
    294         $cache_key = "get_comments:$key:$last_changed";
    295 
    296         if ( $cache = wp_cache_get( $cache_key, 'comment' ) ) {
    297             $this->comments = $cache;
     301        $cache_key = "get_comment_ids:$key:$last_changed";
     302
     303        $comment_ids = wp_cache_get( $cache_key, 'comment' );
     304        if ( false === $comment_ids ) {
     305            $comment_ids = $this->get_comment_ids();
     306            wp_cache_add( $cache_key, $comment_ids, 'comment' );
     307        }
     308
     309        // If querying for a count only, there's nothing more to do.
     310        if ( $this->query_vars['count'] ) {
     311            // $comment_ids is actually a count in this case.
     312            return intval( $comment_ids );
     313        }
     314
     315        $comment_ids = array_map( 'intval', $comment_ids );
     316
     317        if ( 'ids' == $this->query_vars['fields'] ) {
     318            $this->comments = $comment_ids;
    298319            return $this->comments;
    299320        }
    300321
     322        _prime_comment_caches( $comment_ids, $this->query_vars['update_comment_meta_cache'] );
     323
     324        // Fetch full comment objects from the primed cache.
     325        $_comments = array();
     326        foreach ( $comment_ids as $comment_id ) {
     327            if ( $_comment = wp_cache_get( $comment_id, 'comment' ) ) {
     328                $_comments[] = $_comment;
     329            }
     330        }
     331
     332        /**
     333         * Filter the comment query results.
     334         *
     335         * @since 3.1.0
     336         *
     337         * @param array            $results  An array of comments.
     338         * @param WP_Comment_Query &$this    Current instance of WP_Comment_Query, passed by reference.
     339         */
     340        $_comments = apply_filters_ref_array( 'the_comments', array( $_comments, &$this ) );
     341
     342        // Convert to WP_Comment instances
     343        $comments = array_map( 'get_comment', $_comments );
     344
     345        $this->comments = $comments;
     346        return $this->comments;
     347    }
     348
     349    /**
     350     * Used internally to get a list of comment IDs matching the query vars.
     351     *
     352     * @since 4.4.0
     353     * @access protected
     354     *
     355     * @global wpdb $wpdb
     356     */
     357    protected function get_comment_ids() {
     358        global $wpdb;
     359
     360        $groupby = '';
    301361        $where = array();
    302362
     
    472532            $fields = 'COUNT(*)';
    473533        } else {
    474             switch ( strtolower( $this->query_vars['fields'] ) ) {
    475                 case 'ids':
    476                     $fields = "$wpdb->comments.comment_ID";
    477                     break;
    478                 default:
    479                     $fields = "*";
    480                     break;
    481             }
     534            $fields = "$wpdb->comments.comment_ID";
    482535        }
    483536
     
    626679        }
    627680
    628         if ( ! empty( $meta_query_clauses ) ) {
    629             $join .= $meta_query_clauses['join'];
     681        if ( ! empty( $this->meta_query_clauses ) ) {
     682            $join .= $this->meta_query_clauses['join'];
    630683
    631684            // Strip leading 'AND'.
    632             $where[] = preg_replace( '/^\s*AND\s*/', '', $meta_query_clauses['where'] );
     685            $where[] = preg_replace( '/^\s*AND\s*/', '', $this->meta_query_clauses['where'] );
    633686
    634687            if ( ! $this->query_vars['count'] ) {
     
    678731
    679732        if ( $this->query_vars['count'] ) {
    680             return $wpdb->get_var( $this->request );
    681         }
    682 
    683         if ( 'ids' == $this->query_vars['fields'] ) {
    684             $this->comments = $wpdb->get_col( $this->request );
    685             return array_map( 'intval', $this->comments );
    686         }
    687 
    688         $results = $wpdb->get_results( $this->request );
    689         /**
    690          * Filter the comment query results.
    691          *
    692          * @since 3.1.0
    693          *
    694          * @param array            $results  An array of comments.
    695          * @param WP_Comment_Query &$this    Current instance of WP_Comment_Query, passed by reference.
    696          */
    697         $_comments = apply_filters_ref_array( 'the_comments', array( $results, &$this ) );
    698 
    699         // Convert to WP_Comment instances
    700         $comments = array_map( 'get_comment', $_comments );
    701 
    702         wp_cache_add( $cache_key, $comments, 'comment' );
    703         if ( '*' === $fields ) {
    704             update_comment_cache( $comments, $this->query_vars['update_comment_meta_cache'] );
    705         }
    706 
    707         $this->comments = $comments;
    708         return $this->comments;
     733            return intval( $wpdb->get_var( $this->request ) );
     734        } else {
     735            $comment_ids = $wpdb->get_col( $this->request );
     736            return array_map( 'intval', $comment_ids );
     737        }
    709738    }
    710739
Note: See TracChangeset for help on using the changeset viewer.