Skip to:
Content

BuddyPress.org

Opened 3 months ago

Closed 3 months ago

#9203 closed enhancement (invalid)

Cache `BP_Groups_Member::total_group_count()`

Reported by: espellcaste's profile espellcaste Owned by: espellcaste's profile espellcaste
Milestone: Priority: normal
Severity: normal Version:
Component: Performance Keywords:
Cc:

Description

For large communities, this method runs an expensive query that's uncached.

I noticed slow query notices while visiting the https://site.com/groups/ page with a 50k groups dataset.

We should cache it.

Change History (6)

#1 @espellcaste
3 months ago

  • Component changed from Groups to Performance
  • Type changed from defect (bug) to enhancement

#2 @the ank
3 months ago

Hi Mate,

I looked into the issue and I would like to add my notes here as follows -

  1. A parent function already exists groups_total_groups_for_user() which caches the groups count.
  1. If we directly apply the cache method to total_group_count(), it would cause a problem and would not provide a refreshed count as this function is used when someone leaves a group or joins a group and also to get a refreshed total group count.
  1. In case you would like to cache it for your purpose, please find the code below -
public static function total_group_count( $user_id = 0 ) {
		global $wpdb;


		if ( empty( $user_id ) )
			$user_id = bp_displayed_user_id();

		$cache_key = 'total_group_count_' . $user_id;
		$cached_count = get_transient( $cache_key );


		if ( false === $cached_count ) {
			$bp = buddypress();
			if ( $user_id != bp_loggedin_user_id() && !bp_current_user_can( 'bp_moderate' ) ) {
				$count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id AND g.status != 'hidden' AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0", $user_id ) );
			} else {
				$count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0", $user_id ) );
			}

			// Cache the result for 1 hour (3600 seconds)
			set_transient( $cache_key, $count, 3600 );
		} else {
			$count = $cached_count;
		}

		return $count;

	}

Regards

#3 @espellcaste
3 months ago

Thanks! I'll start by confirming why we are not using groups_total_groups_for_user instead. I can see we are calling BP_Groups_Member::total_group_count directly.

Thanks for the feedback.

#4 @the ank
3 months ago

Most Welcome :)

#5 @imath
3 months ago

  • Milestone changed from Up Next to 15.0.0

#6 @espellcaste
3 months ago

  • Keywords needs-patch removed
  • Milestone 15.0.0 deleted
  • Resolution set to invalid
  • Status changed from assigned to closed

Turned out the template is using the right function. The problem was that I was not using an object cache service locally, so the request was going to the db every time.

After adding an object cache service, the cache kicked in and the warning was gone.

Let's resolve this as invalid.

Note: See TracTickets for help on using tickets.