Skip to content

Add index on aggregate_user (user_id, follower_count) - #11657

Merged
stereosteve merged 2 commits into
mainfrom
agg-user-follower-idx
Mar 25, 2025
Merged

Add index on aggregate_user (user_id, follower_count)#11657
stereosteve merged 2 commits into
mainfrom
agg-user-follower-idx

Conversation

@stereosteve

@stereostevestereosteve commented Mar 25, 2025

Copy link
Copy Markdown
Contributor

Most user list modals are sorted by follower_count desc. This index can save db from having to build full result set before doing pagination.

To take our "followers" query:

explain SELECT follower_user_id
from
follows
join users on users.user_id = follows.follower_user_id
join aggregate_user on follower_user_id = aggregate_user.user_id
where
follows.is_current = true
and follows.is_delete = false
and users.is_deactivated = false
and followee_user_id = 1
order by
follower_count desc,
aggregate_user.user_id asc
offset 0
limit 100;

Before:

 QUERY PLAN -------------------------------------------------------------------------------------------------------------------
Limit (cost=11168.09..11168.34 rows=100 width=16)
-> Sort (cost=11168.09..11170.18 rows=838 width=16)
Sort Key: aggregate_user.follower_count DESC, follows.follower_user_id
-> Nested Loop (cost=1.55..11136.06 rows=838 width=16)
-> Nested Loop (cost=1.12..10647.18 rows=838 width=8)
-> Index Scan using follows_inbound_idx on follows (cost=0.56..3418.39 rows=846 width=4)
Index Cond: ((followee_user_id = 1) AND (is_delete = false))
Filter: is_current
-> Index Scan using users_pkey on users (cost=0.56..8.53 rows=1 width=4)
Index Cond: (user_id = follows.follower_user_id)
Filter: (NOT is_deactivated)
-> Index Scan using aggregate_user_table_pkey on aggregate_user (cost=0.43..0.58 rows=1 width=12)
Index Cond: (user_id = users.user_id)
(13 rows)

After:

 QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=7837.26..7837.51 rows=100 width=16)
-> Sort (cost=7837.26..7839.36 rows=838 width=16)
Sort Key: aggregate_user.follower_count DESC, follows.follower_user_id
-> Nested Loop (cost=27.13..7805.24 rows=838 width=16)
Join Filter: (follows.follower_user_id = users.user_id)
-> Nested Loop (cost=26.57..6971.44 rows=846 width=16)
-> Bitmap Heap Scan on follows (cost=26.14..3328.85 rows=846 width=4)
Recheck Cond: (followee_user_id = 1)
Filter: (is_current AND (NOT is_delete))
-> Bitmap Index Scan on follows_inbound_idx (cost=0.00..25.93 rows=846 width=0)
Index Cond: ((followee_user_id = 1) AND (is_delete = false))
-> Index Only Scan using idx_aggregate_user_follower_count on aggregate_user (cost=0.43..4.31 rows=1 width=12)
Index Cond: (user_id = follows.follower_user_id)
-> Index Scan using users_pkey on users (cost=0.56..0.97 rows=1 width=4)
Index Cond: (user_id = aggregate_user.user_id)
Filter: (NOT is_deactivated)
(16 rows)

30% reduction in cost esitmate.

Most user list modals are sorted by follower_count desc.
This index can save db from having to build full result set before doing pagination.
@changeset-bot

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 42a2cb4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@stereosteve
stereosteve enabled auto-merge (squash) March 25, 2025 16:34
@stereosteve
stereosteve merged commit 07a3f7b into mainMar 25, 2025
@stereosteve
stereosteve deleted the agg-user-follower-idx branch March 25, 2025 16:49
audius-infra pushed a commit that referenced this pull request Mar 26, 2025
[f1b7253] hotfix: Prioritize users with handles when fetching users by wallet (#11667) Marcus Pasell
[68a1eb0] hotfix: Unblock payment router indexing with duplicate wallets (#11666) Marcus Pasell
[7188521] fix missing types for archiver (#11663) Randy Schott
[4229ed9] [PE-5849] Change listen streak window to 16-48 hours (#11662) Reed
[dab8846] Faster + more correct mutuals endpoint. (#11660) Steve Perkins
[73ed1e3] Enable tastemaker challenge on prod (should wait for block 1120000) (#11659) Reed
[07a3f7b] Add index on aggregate_user (user_id, follower_count) (#11657) Steve Perkins
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@stereosteve@rickyrombo