Skip to content

Commit a63d948

Browse files
committed
Optimize slow query
1 parent 09c33f1 commit a63d948

File tree

3 files changed

+54
-21
lines changed

3 files changed

+54
-21
lines changed

src/sentry/api/endpoints/organization_releases.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@
3030
from sentry.models.activity import Activity
3131
from sentry.models.orgauthtoken import is_org_auth_token_auth, update_org_auth_token_last_used
3232
from sentry.models.project import Project
33-
from sentry.models.release import Release, ReleaseStatus
33+
from sentry.models.release import (
34+
Release,
35+
ReleaseStatus,
36+
filter_releases_by_environments,
37+
filter_releases_by_projects,
38+
)
3439
from sentry.models.releases.exceptions import ReleaseCommitError
3540
from sentry.models.releases.release_project import ReleaseProject
3641
from sentry.models.releases.util import SemverFilter
@@ -307,7 +312,11 @@ def get(self, request: Request, organization) -> Response:
307312
# health data in the last 24 hours.
308313
debounce_update_release_health_data(organization, filter_params["project_id"])
309314

310-
queryset = Release.objects.filter(organization=organization)
315+
queryset = Release.objects.filter(organization_id=organization.id)
316+
queryset = filter_releases_by_environments(
317+
queryset, [e.id for e in filter_params.get("environment_objects", [])]
318+
)
319+
queryset = queryset.annotate(date=F("date_added"))
311320

312321
if status_filter:
313322
try:
@@ -320,9 +329,6 @@ def get(self, request: Request, organization) -> Response:
320329
else:
321330
queryset = queryset.filter(status=status_int)
322331

323-
queryset = queryset.annotate(date=F("date_added"))
324-
325-
queryset = add_environment_to_queryset(queryset, filter_params)
326332
if query:
327333
try:
328334
queryset = _filter_releases_by_query(queryset, organization, query, filter_params)
@@ -333,12 +339,11 @@ def get(self, request: Request, organization) -> Response:
333339
)
334340

335341
select_extra = {}
336-
337-
queryset = queryset.distinct()
338342
if flatten:
343+
queryset = queryset.filter(projects__id__in=filter_params["project_id"])
339344
select_extra["_for_project_id"] = "sentry_release_project.project_id"
340-
341-
queryset = queryset.filter(projects__id__in=filter_params["project_id"])
345+
else:
346+
queryset = filter_releases_by_projects(queryset, filter_params["project_id"])
342347

343348
if sort == "date":
344349
queryset = queryset.order_by("-date")
@@ -664,20 +669,16 @@ def get(self, request: Request, organization) -> Response:
664669
except NoProjects:
665670
return Response([])
666671

672+
queryset = Release.objects.filter(organization_id=organization.id)
673+
queryset = add_date_filter_to_queryset(queryset, filter_params)
674+
queryset = filter_releases_by_projects(queryset, filter_params["project_id"])
675+
queryset = filter_releases_by_environments(
676+
queryset, [e.id for e in filter_params.get("environment_objects", [])]
677+
)
667678
queryset = (
668-
Release.objects.filter(
669-
organization=organization, projects__id__in=filter_params["project_id"]
670-
)
671-
.annotate(
672-
date=F("date_added"),
673-
)
674-
.values("version", "date")
675-
.order_by("-date")
676-
.distinct()
679+
queryset.annotate(date=F("date_added")).values("version", "date").order_by("-date")
677680
)
678681

679-
queryset = add_date_filter_to_queryset(queryset, filter_params)
680-
queryset = add_environment_to_queryset(queryset, filter_params)
681682
if query:
682683
try:
683684
queryset = _filter_releases_by_query(queryset, organization, query, filter_params)

src/sentry/models/release.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from django.utils import timezone
1414
from django.utils.functional import cached_property
1515
from django.utils.translation import gettext_lazy as _
16+
from django_stubs_ext import QuerySetAny
1617
from sentry_relay.exceptions import RelayError
1718
from sentry_relay.processing import parse_release
1819

@@ -32,6 +33,7 @@
3233
from sentry.db.models.manager.base import BaseManager
3334
from sentry.models.artifactbundle import ArtifactBundle
3435
from sentry.models.commitauthor import CommitAuthor
36+
from sentry.models.releaseprojectenvironment import ReleaseProjectEnvironment
3537
from sentry.models.releases.constants import (
3638
DB_VERSION_LENGTH,
3739
ERR_RELEASE_HEALTH_DATA,
@@ -818,3 +820,33 @@ def get_previous_release(release: Release) -> Release | None:
818820
.order_by("-sort")
819821
.first()
820822
)
823+
824+
825+
def filter_releases_by_projects(queryset: QuerySetAny, project_ids: list[int]):
826+
"""Return releases belonging to a project."""
827+
if not project_ids:
828+
return queryset
829+
830+
return queryset.filter(
831+
Exists(
832+
ReleaseProject.objects.filter(
833+
release=OuterRef("pk"),
834+
project_id__in=project_ids,
835+
)
836+
)
837+
)
838+
839+
840+
def filter_releases_by_environments(queryset: QuerySetAny, environment_ids: list[int]):
841+
"""Return a release queryset filtered by environments."""
842+
if not environment_ids:
843+
return queryset
844+
845+
return queryset.filter(
846+
Exists(
847+
ReleaseProjectEnvironment.objects.filter(
848+
release=OuterRef("pk"),
849+
environment_id__in=environment_ids,
850+
)
851+
)
852+
)

tests/sentry/api/endpoints/test_organization_releases.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ def test_release_filter(self):
325325
release = Release.objects.create(
326326
organization_id=org.id,
327327
version="foobar",
328-
date_added=datetime(2013, 8, 13, 3, 8, 24, 880386, tzinfo=UTC),
328+
date_added=datetime(2013, 8, 13, 3, 8, 24, 880387, tzinfo=UTC),
329329
)
330330
release.add_project(project)
331331

0 commit comments

Comments
 (0)