Skip to:
Content

BuddyPress.org

Changeset 8491


Ignore:
Timestamp:
06/09/2014 06:33:05 PM (12 years ago)
Author:
boonebgorges
Message:

Disable COUNT queries by default in bp_activity_get() stack

The COUNT query performed to get the total activity count has proven to be a
performance bottleneck on large sites. Moreover, the way that activity items
are displayed on the front end (using the Load More link) means that the total
count is not actually used by BuddyPress in most cases. To reduce query
overhead, we introduce a 'count_total' parameter to the bp_activity_get()
stack, and set it to false by default.

For backward compatibility, a few additional changes are introduced:

  • In the activity-loop.php template, the <noscript> pagination markup is removed. In its place, the Load More link is refactored so that it loads the next available page of activity items.
  • The mechanism used to determine whether there are more activity items to show (bp_activity_has_more_items()) has been refined; when no COUNT query takes place, we query for the $per_page value + 1 to infer whether more items are available.

Fixes #5629

Props boonebgorges, r-a-y

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-activity/bp-activity-admin.php

    r8485 r8491  
    10581058                        'show_hidden'      => true,
    10591059                        'spam'             => 'spam_only',
     1060                        'count_total'      => 'count_query',
    10601061                ) );
    10611062                $this->spam_count = $spams['total'];
    … …  
    10731074                        //'sort'             => $sort,
    10741075                        'spam'             => $spam,
     1076                        'count_total'      => 'count_query',
    10751077                ) );
    10761078
  • trunk/src/bp-activity/bp-activity-classes.php

    r8251 r8491  
    268268         *     @type bool $update_meta_cache Whether to pre-fetch metadata for
    269269         *           queried activity items. Default: true.
     270         *     @type string|bool $count_total If true, an additional DB query
     271         *           is run to count the total activity items for the query.
     272         *           Default: false.
    270273         * }
    271274         * @return array The array returned has two keys:
    … …  
    312315                        'spam'              => 'ham_only', // Spam status
    313316                        'update_meta_cache' => true,
     317                        'count_total'       => false,
    314318                );
    315319                $r = wp_parse_args( $args, $defaults );
    … …  
    412416                $per_page = absint( $per_page );
    413417
     418                $retval = array(
     419                        'activities'     => null,
     420                        'total'          => null,
     421                        'has_more_items' => null,
     422                );
     423
    414424                // Filter and return true to use the legacy query structure (not recommended)
    415425                if ( apply_filters( 'bp_use_legacy_activity_query', false, __METHOD__, $r ) ) {
    … …  
    432442
    433443                        if ( ! empty( $per_page ) && ! empty( $page ) ) {
    434                                 $activity_ids_sql .= $wpdb->prepare( " LIMIT %d, %d", absint( ( $page - 1 ) * $per_page ), $per_page );
     444                                // We query for $per_page + 1 items in order to
     445                                // populate the has_more_items flag
     446                                $activity_ids_sql .= $wpdb->prepare( " LIMIT %d, %d", absint( ( $page - 1 ) * $per_page ), $per_page + 1 );
    435447                        }
    436448
    … …  
    438450
    439451                        $activity_ids = $wpdb->get_col( $activity_ids_sql );
    440                         $activities   = self::get_activity_data( $activity_ids );
    441                 }
    442 
    443                 $total_activities_sql = apply_filters( 'bp_activity_total_activities_sql', "SELECT count(DISTINCT a.id) FROM {$bp->activity->table_name} a {$join_sql} {$where_sql}", $where_sql, $sort );
    444                 $total_activities     = $wpdb->get_var( $total_activities_sql );
     452
     453                        $retval['has_more_items'] = ! empty( $per_page ) && count( $activity_ids ) > $per_page;
     454
     455                        // If we've fetched more than the $per_page value, we
     456                        // can discard the extra now
     457                        if ( ! empty( $per_page ) && count( $activity_ids ) === $per_page + 1 ) {
     458                                array_pop( $activity_ids );
     459                        }
     460
     461                        $activities = self::get_activity_data( $activity_ids );
     462                }
    445463
    446464                // Get the fullnames of users so we don't have to query in the loop
    … …  
    466484                $activities = BP_Activity_Activity::generate_action_strings( $activities );
    467485
     486                $retval['activities'] = $activities;
     487
    468488                // If $max is set, only return up to the max results
    469                 if ( !empty( $max ) ) {
    470                         if ( (int) $total_activities > (int) $max )
    471                                 $total_activities = $max;
    472                 }
    473 
    474                 return array( 'activities' => $activities, 'total' => (int) $total_activities );
     489                if ( ! empty( $r['count_total'] ) ) {
     490
     491                        $total_activities_sql = apply_filters( 'bp_activity_total_activities_sql', "SELECT count(DISTINCT a.id) FROM {$bp->activity->table_name} a {$join_sql} {$where_sql}", $where_sql, $sort );
     492                        $total_activities     = $wpdb->get_var( $total_activities_sql );
     493
     494                        if ( !empty( $max ) ) {
     495                                if ( (int) $total_activities > (int) $max )
     496                                        $total_activities = $max;
     497                        }
     498
     499                        $retval['total'] = $total_activities;
     500                }
     501
     502                return $retval;
    475503        }
    476504
  • trunk/src/bp-activity/bp-activity-functions.php

    r8428 r8491  
    964964                'spam'              => 'ham_only',   // 'ham_only' (default), 'spam_only' or 'all'.
    965965                'update_meta_cache' => true,
     966                'count_total'       => false,
    966967
    967968                /**
    … …  
    995996                                'spam'              => $spam,
    996997                                'update_meta_cache' => $update_meta_cache,
     998                                'count_total'       => $count_total,
    997999                        );
    9981000                        $activity = BP_Activity_Activity::get( $args );
    … …  
    10131015                        'exclude'          => $exclude,
    10141016                        'in'               => $in,
    1015                         'spam'             => $spam
     1017                        'spam'             => $spam,
     1018                        'count_total'      => $count_total,
    10161019                );
    10171020                $activity = BP_Activity_Activity::get( $args );
  • trunk/src/bp-activity/bp-activity-template.php

    r8477 r8491  
    9898
    9999        var $in_the_loop;
     100
     101        /**
     102         * URL parameter key for activity pagination. Default: 'acpage'.
     103         *
     104         * @since BuddyPress (2.1.0)
     105         * @var string
     106         */
     107        var $pag_arg;
    100108
    101109        var $pag_page;
    … …  
    179187                extract( $r );
    180188
    181                 $this->pag_page = isset( $_REQUEST[$page_arg] ) ? intval( $_REQUEST[$page_arg] ) : $page;
     189                $this->pag_arg  = $r['page_arg'];
     190                $this->pag_page = isset( $_REQUEST[ $this->pag_arg ] ) ? intval( $_REQUEST[ $this->pag_arg ] ) : $page;
    182191                $this->pag_num  = isset( $_REQUEST['num'] ) ? intval( $_REQUEST['num'] ) : $per_page;
    183192
    … …  
    221230                }
    222231
    223                 if ( !$max || $max >= (int) $this->activities['total'] )
    224                         $this->total_activity_count = (int) $this->activities['total'];
    225                 else
    226                         $this->total_activity_count = (int) $max;
     232                // The total_activity_count property will be set only if a
     233                // 'count_total' query has taken place
     234                if ( ! is_null( $this->activities['total'] ) ) {
     235                        if ( ! $max || $max >= (int) $this->activities['total'] ) {
     236                                $this->total_activity_count = (int) $this->activities['total'];
     237                        } else {
     238                                $this->total_activity_count = (int) $max;
     239                        }
     240                }
     241
     242                $this->has_more_items = $this->activities['has_more_items'];
    227243
    228244                $this->activities = $this->activities['activities'];
    … …  
    707723
    708724/**
     725 * Output the URL for the Load More link.
     726 *
     727 * @since BuddyPress (2.1.0)
     728 */
     729function bp_activity_load_more_link() {
     730        echo bp_get_activity_load_more_link();
     731}
     732        function bp_get_activity_load_more_link() {
     733                global $activities_template;
     734
     735                $link = bp_get_requested_url();
     736                $link = add_query_arg( $activities_template->pag_arg, $activities_template->pag_page + 1, $link );
     737
     738                return apply_filters( 'bp_get_activity_load_more_link', $link );
     739        }
     740
     741/**
    709742 * Output the activity pagination count.
    710743 *
    … …  
    779812        global $activities_template;
    780813
    781         $remaining_pages = 0;
    782 
    783         if ( ! empty( $activities_template->pag_page ) ) {
    784                 $remaining_pages = floor( ( $activities_template->total_activity_count - 1 ) / ( $activities_template->pag_num * $activities_template->pag_page ) );
    785         }
    786 
    787         $has_more_items  = (int) $remaining_pages ? true : false;
     814        if ( ! empty( $activities_template->has_more_items )  ) {
     815                $has_more_items = true;
     816        } else {
     817                $remaining_pages = 0;
     818
     819                if ( ! empty( $activities_template->pag_page ) ) {
     820                        $remaining_pages = floor( ( $activities_template->total_activity_count - 1 ) / ( $activities_template->pag_num * $activities_template->pag_page ) );
     821                }
     822
     823                $has_more_items = (int) $remaining_pages > 0;
     824        }
    788825
    789826        return apply_filters( 'bp_activity_has_more_items', $has_more_items );
  • trunk/src/bp-templates/bp-legacy/buddypress/activity/activity-loop.php

    r8155 r8491  
    22
    33<?php if ( bp_has_activities( bp_ajax_querystring( 'activity' ) ) ) : ?>
    4 
    5         <?php /* Show pagination if JS is not enabled, since the "Load More" link will do nothing */ ?>
    6         <noscript>
    7                 <div class="pagination">
    8                         <div class="pag-count"><?php bp_activity_pagination_count(); ?></div>
    9                         <div class="pagination-links"><?php bp_activity_pagination_links(); ?></div>
    10                 </div>
    11         </noscript>
    124
    135        <?php if ( empty( $_POST['page'] ) ) : ?>
    … …  
    2618
    2719                <li class="load-more">
    28                         <a href="#more"><?php _e( 'Load More', 'buddypress' ); ?></a>
     20                        <a href="<?php bp_activity_load_more_link() ?>"><?php _e( 'Load More', 'buddypress' ); ?></a>
    2921                </li>
    3022
  • trunk/tests/phpunit/testcases/activity/class.BP_Activity_Activity.php

    r8251 r8491  
    136136                                ),
    137137                        ),
     138                        'count_total' => 'count_query',
    138139                ) );
    139140
    … …  
    312313
    313314        /**
     315         * @group get
     316         * @group count_total
     317         */
     318        public function test_get_with_count_total() {
     319                $a1 = $this->factory->activity->create();
     320                $a2 = $this->factory->activity->create();
     321
     322                $activity = BP_Activity_Activity::get( array(
     323                        'count_total' => 'count_query',
     324                ) );
     325
     326                $this->assertEquals( 2, $activity['total'] );
     327        }
     328
     329        /**
     330         * @group get
     331         * @group count_total
     332         */
     333        public function test_get_with_count_total_false() {
     334                $a1 = $this->factory->activity->create();
     335                $a2 = $this->factory->activity->create();
     336
     337                $activity = BP_Activity_Activity::get( array(
     338                        'count_total' => false,
     339                ) );
     340
     341                $this->assertSame( null, $activity['total'] );
     342        }
     343
     344        /**
     345         * @group get
     346         * @group count_total
     347         */
     348        public function test_get_with_count_total_default_to_false() {
     349                $a1 = $this->factory->activity->create();
     350                $a2 = $this->factory->activity->create();
     351
     352                $activity = BP_Activity_Activity::get();
     353
     354                $this->assertSame( null, $activity['total'] );
     355        }
     356
     357        /**
    314358         * @group get_id
    315359         */
  • trunk/tests/phpunit/testcases/activity/template.php

    r8402 r8491  
    376376                $activities_template = null;
    377377        }
     378
     379        /**
     380         * @group bp_activity_has_more_items
     381         */
     382        public function test_bp_activity_has_more_items_no_count_total_false() {
     383                $a1 = $this->factory->activity->create();
     384                $a2 = $this->factory->activity->create();
     385
     386                $args = array(
     387                        'count_total' => false,
     388                );
     389
     390                if ( bp_has_activities( $args ) ) {
     391                        global $activities_template;
     392                        $this->assertFalse( bp_activity_has_more_items() );
     393                        $activities_template = null;
     394                }
     395        }
     396
     397        /**
     398         * @group bp_activity_has_more_items
     399         */
     400        public function test_bp_activity_has_more_items_no_count_total_true() {
     401                $a1 = $this->factory->activity->create();
     402                $a2 = $this->factory->activity->create();
     403                $a3 = $this->factory->activity->create();
     404                $a4 = $this->factory->activity->create();
     405
     406                $args = array(
     407                        'count_total' => false,
     408                        'per_page' => 2,
     409                );
     410
     411                if ( bp_has_activities( $args ) ) {
     412                        global $activities_template;
     413                        $this->assertTrue( bp_activity_has_more_items() );
     414                        $activities_template = null;
     415                }
     416        }
     417
     418        /**
     419         * @group bp_activity_has_more_items
     420         */
     421        public function test_bp_activity_has_more_items_count_total_false() {
     422                $a1 = $this->factory->activity->create();
     423                $a2 = $this->factory->activity->create();
     424                $a3 = $this->factory->activity->create();
     425                $a4 = $this->factory->activity->create();
     426
     427                $args = array(
     428                        'count_total' => 'count_query',
     429                );
     430
     431                if ( bp_has_activities( $args ) ) {
     432                        global $activities_template;
     433                        $this->assertFalse( bp_activity_has_more_items() );
     434                        $activities_template = null;
     435                }
     436        }
     437
     438        /**
     439         * @group bp_activity_has_more_items
     440         */
     441        public function test_bp_activity_has_more_items_count_total_true() {
     442                $a1 = $this->factory->activity->create();
     443                $a2 = $this->factory->activity->create();
     444                $a3 = $this->factory->activity->create();
     445                $a4 = $this->factory->activity->create();
     446
     447                $args = array(
     448                        'count_total' => 'count_query',
     449                        'per_page' => 2,
     450                );
     451
     452                if ( bp_has_activities( $args ) ) {
     453                        global $activities_template;
     454                        $this->assertTrue( bp_activity_has_more_items() );
     455                        $activities_template = null;
     456                }
     457        }
    378458}
  • trunk/tests/phpunit/testcases/blogs/functions.php

    r8133 r8491  
    403403                ) );
    404404
    405                 return ! empty( $a['total'] );
     405                return ! empty( $a['activities'] );
    406406        }
    407407}
  • trunk/tests/phpunit/testcases/xprofile/activity.php

    r8212 r8491  
    105105                                'action' => 'updated_profile',
    106106                        ),
     107                        'count_total' => 'count_query',
    107108                ) );
    108109
    … …  
    139140                                'action' => 'updated_profile',
    140141                        ),
     142                        'count_total' => 'count_query',
    141143                ) );
    142144
Note: See TracChangeset for help on using the changeset viewer.