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.
This commit is contained in:
Noah Petherbridge 2024-06-19 14:42:57 -07:00
parent 616f6ae76b
commit 02ec0a9116

View File

@ -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,
)
}