From 02ec0a9116b29d321e325e95d569c96ba59c406c Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Wed, 19 Jun 2024 14:42:57 -0700 Subject: [PATCH] Optimize Site Gallery query for massive friend lists Instead of selecting the full array of friend user IDs and pasting that into the main query, use subselects for hopefully better performance. --- pkg/models/photo.go | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/pkg/models/photo.go b/pkg/models/photo.go index bedc157..973418f 100644 --- a/pkg/models/photo.go +++ b/pkg/models/photo.go @@ -497,7 +497,6 @@ func PaginateGalleryPhotos(user *User, conf Gallery, pager *Pagination) ([]*Phot explicitOK = user.Explicit // User opted-in for explicit content blocklist = BlockedUserIDs(user) - friendIDs = FriendIDs(userID) privateUserIDs = PrivateGrantedUserIDs(userID) privateUserIDsAreFriends = PrivateGrantedUserIDsAreFriends(user) wheres = []string{} @@ -525,8 +524,13 @@ func PaginateGalleryPhotos(user *User, conf Gallery, pager *Pagination) ([]*Phot // Admins see everything on the site (only an admin user can get an admin view). adminView = user.HasAdminScope(config.ScopePhotoModerator) && adminView - // Include ourself in our friend IDs. - friendIDs = append(friendIDs, userID) + // Friend IDs subquery, used in a "WHERE user_id IN ?" clause. + friendsQuery := fmt.Sprintf(`( + SELECT target_user_id + FROM friends + WHERE source_user_id = %d + AND approved IS TRUE + )`, userID) // What sets of User ID * Visibility filters to query under? var ( @@ -539,17 +543,22 @@ func PaginateGalleryPhotos(user *User, conf Gallery, pager *Pagination) ([]*Phot // Shy users can only see their Friends photos (public or friends visibility) // and any Private photos to whom they were granted access. visOrs = append(visOrs, + fmt.Sprintf("(user_id IN %s AND visibility IN ?)", friendsQuery), "(user_id IN ? AND visibility IN ?)", - "(user_id IN ? AND visibility IN ?)", + "user_id = ?", ) visPlaceholders = append(visPlaceholders, - friendIDs, photosFriends, + photosFriends, privateUserIDs, photosPrivate, + userID, ) } else if friendsOnly { // User wants to see only self and friends photos. - visOrs = append(visOrs, "(user_id IN ? AND visibility IN ?)") - visPlaceholders = append(visPlaceholders, friendIDs, photosFriends) + visOrs = append(visOrs, + fmt.Sprintf("(user_id IN %s AND visibility IN ?)", friendsQuery), + "user_id = ?", + ) + visPlaceholders = append(visPlaceholders, photosFriends, userID) // If their friends granted private photos, include those too. if len(privateUserIDsAreFriends) > 0 { @@ -559,14 +568,16 @@ func PaginateGalleryPhotos(user *User, conf Gallery, pager *Pagination) ([]*Phot } else { // You can see friends' Friend photos but only public for non-friends. visOrs = append(visOrs, + fmt.Sprintf("(user_id IN %s AND visibility IN ?)", friendsQuery), "(user_id IN ? AND visibility IN ?)", - "(user_id IN ? AND visibility IN ?)", - "(user_id NOT IN ? AND visibility IN ?)", + fmt.Sprintf("(user_id NOT IN %s AND visibility IN ?)", friendsQuery), + "user_id = ?", ) visPlaceholders = append(placeholders, - friendIDs, photosFriends, + photosFriends, privateUserIDs, photosPrivate, - friendIDs, photosPublic, + photosPublic, + userID, ) }