Browse Source

fix(api): Improve rate limit query (#67287)

The subquery that we use for fetching the sentry app installation is
slow because we're joining `SentryAppInstallationToken` and
`SentryAppInstallation`.

Instead, speed it up by fetching `SentryAppInstallationToken`
independently first.

Real query info for the `SentryAppInstallationToken` query
```
Index Scan using sentry_sentryappinstallationtoken_api_token_id on sentry_sentryappinstallationtoken (cost=0.29..2.51 rows=1 width=8) (actual time=0.040..0.041 rows=1 loops=1)
	
Index Cond: (api_token_id = 408727)
	
Planning Time: 0.065 ms
	
Execution Time: 0.052 ms
```

---------

Co-authored-by: Mark Story <mark@mark-story.com>
Seiji Chew 11 months ago
parent
commit
61a1c46cc6
1 changed files with 6 additions and 5 deletions
  1. 6 5
      src/sentry/services/hybrid_cloud/app/impl.py

+ 6 - 5
src/sentry/services/hybrid_cloud/app/impl.py

@@ -3,7 +3,7 @@ from __future__ import annotations
 from collections.abc import Callable, Mapping
 from typing import Any
 
-from django.db.models import QuerySet
+from django.db.models import Q, QuerySet
 
 from sentry.api.serializers import SentryAppAlertRuleActionSerializer, Serializer, serialize
 from sentry.constants import SentryAppInstallationStatus, SentryAppStatus
@@ -203,14 +203,15 @@ class DatabaseBackedAppService(AppService):
                 # the installation by token id in SentryAppInstallation, we also search
                 # SentryAppInstallationToken by token id, then fetch  the linked installation.
                 # Internal Integrations follow this pattern because they can have multiple tokens.
-                from django.db.models import Q, Subquery
 
-                subquery = SentryAppInstallationToken.objects.filter(
+                # Decompose this query instead of using a subquery for performance.
+                install_token_list = SentryAppInstallationToken.objects.filter(
                     api_token_id=filters["api_installation_token_id"],
-                ).values("sentry_app_installation_id")
+                ).values_list("sentry_app_installation_id", flat=True)
+
                 query = query.filter(
                     Q(api_token_id=filters["api_installation_token_id"])
-                    | Q(id__in=Subquery(subquery))
+                    | Q(id__in=list(install_token_list))
                 )
 
             return query