Skip to content

Commit dbb0dd2

Browse files
scttcperclaude
andcommitted
perf(issues): Fix N+1 queries in starred views endpoint
The starred views serializer was calling serialize() per item, which triggered separate get_attrs() calls for each starred view — roughly 4N+1 queries for N views. Batch-serialize all views in get_attrs() instead. Also adds prefetch_related for the projects M2M and switches values_list() to .all() so the prefetch cache is actually used. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0be518e commit dbb0dd2

File tree

3 files changed

+16
-12
lines changed

3 files changed

+16
-12
lines changed

src/sentry/api/serializers/models/groupsearchview.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def get_attrs(self, item_list, user, **kwargs) -> MutableMapping[Any, Any]:
6868
return attrs
6969

7070
def serialize(self, obj, attrs, user, **kwargs) -> GroupSearchViewSerializerResponse:
71-
projects = [-1] if obj.is_all_projects else list(obj.projects.values_list("id", flat=True))
71+
projects = [-1] if obj.is_all_projects else [p.id for p in obj.projects.all()]
7272

7373
return {
7474
"id": str(obj.id),

src/sentry/api/serializers/models/groupsearchviewstarred.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from sentry.api.serializers import Serializer, register, serialize
44
from sentry.api.serializers.models.groupsearchview import (
55
GroupSearchViewSerializer,
6-
GroupSearchViewSerializerResponse,
76
)
87
from sentry.models.groupsearchviewstarred import GroupSearchViewStarred
98
from sentry.models.savedsearch import SORT_LITERALS
@@ -28,13 +27,14 @@ def __init__(self, *args, **kwargs):
2827
self.organization = kwargs.pop("organization", None)
2928
super().__init__(*args, **kwargs)
3029

31-
def serialize(self, obj, attrs, user, **kwargs) -> GroupSearchViewStarredSerializerResponse:
32-
serialized_view: GroupSearchViewSerializerResponse = serialize(
33-
obj.group_search_view,
30+
def get_attrs(self, item_list, user, **kwargs):
31+
views = [item.group_search_view for item in item_list]
32+
serialized_views = serialize(
33+
views,
3434
user,
35-
serializer=GroupSearchViewSerializer(
36-
organization=self.organization,
37-
),
35+
serializer=GroupSearchViewSerializer(organization=self.organization),
3836
)
37+
return dict(zip(item_list, serialized_views))
3938

40-
return serialized_view
39+
def serialize(self, obj, attrs, user, **kwargs) -> GroupSearchViewStarredSerializerResponse:
40+
return attrs

src/sentry/issues/endpoints/organization_group_search_views_starred.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,13 @@ def get(self, request: Request, organization: Organization) -> Response:
3131
"""
3232

3333
assert request.user.id is not None
34-
starred_views = GroupSearchViewStarred.objects.filter(
35-
organization=organization, user_id=request.user.id
36-
).select_related("group_search_view")
34+
starred_views = (
35+
GroupSearchViewStarred.objects.filter(
36+
organization=organization, user_id=request.user.id
37+
)
38+
.select_related("group_search_view")
39+
.prefetch_related("group_search_view__projects")
40+
)
3741

3842
return self.paginate(
3943
request=request,

0 commit comments

Comments
 (0)