perf(hybridcloud): Skip correlated subqueries in user.serialize_many#112500
Merged
perf(hybridcloud): Skip correlated subqueries in user.serialize_many#112500
Conversation
base_query() adds 5 correlated subqueries via .extra() (permissions, roles, useremails, authenticators, useravatar) that are only consumed by serialize_rpc_user() in the get_many path. serialize_many goes through the API serializer which re-queries the same data via get_attrs(), so the extra subqueries were pure overhead. Pass select_related=False so serialize_many gets a plain queryset. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of changing the default for all FilterQueryDatabaseImpl subclasses, expose select_related as a parameter on serialize_many and have the user service opt in. Safer since only the user service is affected. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
george-sentry
pushed a commit
that referenced
this pull request
Apr 9, 2026
…112500) https://github.com/getsentry/sentry/blob/a8fcbce0cc94e981c42ef26c033fb9eb56b1b03d/src/sentry/users/services/user/impl.py#L358-L375 `base_query()` adds 5 correlated subqueries via `.extra()` (permissions, roles, useremails, authenticators, useravatar) that are only consumed by `serialize_rpc_user()` in the `get_many` path. `serialize_many` goes through the API serializer which re-queries the same data in `get_attrs()`, so the extra subqueries were pure overhead - the data was fetched, attached to the User objects, and then ignored. Threads `select_related` through `FilterQueryDatabaseImpl.serialize_many` as an opt-in parameter and has the user service pass `False`. The `select_related=False` escape hatch already exists (added after #48088) and is used by `get_many_ids` and `get_many_profiles`, but `serialize_many` wasn't using it. Context: #45564 moved `base_query` into `FilterQueryDatabaseImpl`, #48088 added the eager-loaded subqueries to fix N+1s in the `serialize_rpc` path. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
sentry/src/sentry/users/services/user/impl.py
Lines 358 to 375 in a8fcbce
base_query()adds 5 correlated subqueries via.extra()(permissions, roles, useremails, authenticators, useravatar) that are only consumed byserialize_rpc_user()in theget_manypath.serialize_manygoes through the API serializer which re-queries the same data inget_attrs(), so the extra subqueries were pure overhead - the data was fetched, attached to the User objects, and then ignored.Threads
select_relatedthroughFilterQueryDatabaseImpl.serialize_manyas an opt-in parameter and has the user service passFalse. Theselect_related=Falseescape hatch already exists (added after #48088) and is used byget_many_idsandget_many_profiles, butserialize_manywasn't using it.Context: #45564 moved
base_queryintoFilterQueryDatabaseImpl, #48088 added the eager-loaded subqueries to fix N+1s in theserialize_rpcpath.