[wp-trac] [WordPress Trac] #31746: get_blogs_of_user() can be very slow when a user is a member of thousands of sites

WordPress Trac noreply at wordpress.org
Wed Apr 27 12:32:29 UTC 2016


#31746: get_blogs_of_user() can be very slow when a user is a member of thousands
of sites
--------------------------+-----------------------------
 Reporter:  jtsternberg   |       Owner:  johnbillion
     Type:  defect (bug)  |      Status:  reviewing
 Priority:  normal        |   Milestone:  Future Release
Component:  Users         |     Version:  3.0
 Severity:  normal        |  Resolution:
 Keywords:  has-patch     |     Focuses:  multisite
--------------------------+-----------------------------

Comment (by nerrad):

 Replying to [comment:19 ericlewis]:
 > Alternatively, we could try to avoid calling `get_blogs_of_user()` in
 the places @jtsternberg mentioned in the original post.

 There still would need to be a replacement for what its called for.  Long
 term, there still needs to be something to allow `get_blogs_of_user()` to
 be more performant. The main reason why this function is so slow is
 because of this line:

 `$keys = get_user_meta( $user_id );`.  All info about the blogs a user
 belongs to is inferred from data used to store capabilities for a user on
 a blog AND thus ALL user meta has to be retrieved in order to grab that
 data.  Then each meta key/value is LOOPED through and an additional query
 is done to get the blog details (querypalooza).  This means (contrary to
 my earlier suggestion) efficient paging can't be done.

 Long term, there needs to be a better way to indicate the blogs a user
 belongs to that can be

 a. easily queried.
 b. can be paged.

 A couple ways (so far) that I can think of for doing this are:

 == Option 1: Track the blogs a user belongs to via its own user_meta
 key/value pair.

 Each blog a user belongs to is a record with a common prefix (maybe
 `user_blog` => `{$blog_id}`).  With that, the query for getting all the
 blogs a user belongs to can be simplified and pages (and even to some
 degree, joined with the blog table.

 == Option 2: Add a new table ==

  Another way of accomplishing a more performant way to get the blogs a
 user belongs to is to rework how capabilities (gasp another core wp
 system) are done a bit so capabilities are tracked in a separate table
 called `user_capabilities` where we have:

 user_cap_id | blog_id | user_id | capabilities

 On single site installs blog_id will always be 1 and this table will have
 little information.  However on multi-sites this table because immediately
 more useful because its more scalable.  It serves as both a join table for
 user -> blog and tracks the capabilities the user has on that blog.
 Feasibly this could also be used to track user information that is
 specific to blog.

 == Wrap Up ==

 Option one is definitely the quicker win because it requires less code
 changes elsewhere.  However, option 2 gives us the benefits of less data
 stored in the database, more scalability, and clearer representation of
 the data.  The tradeoff of course is the impact on the capability system
 (ugh).  The ONLY reason I suggested using this for storing capabilities is
 because it doesn't make sense to create a brand new table just for joining
 blogs to users (although there's benefits to doing so to) and IF we create
 a new table, we should try to think of other problems this new table could
 help solve.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/31746#comment:20>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list