Skip to content

perf(pr-metrics): Look up commit ids before resolving PR group links - #127927

Draft
scttcper wants to merge 1 commit into
masterfrom
scttcper/pr-metrics-materialize-commit-ids
Draft

scttcper wants to merge 1 commit into
masterfrom
scttcper/pr-metrics-materialize-commit-ids

Conversation

@scttcper

@scttcper scttcper commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

resolved_group_ids passed the commit lookup into the GroupLink query as a subquery inside an OR. Postgres can't use a subquery there as an index lookup, so every call read all ~427k commit resolve links and filtered them afterwards. Look up the commit ids first and pass them as a list, so both sides of the OR are index lookups.

-- before
SELECT DISTINCT group_id FROM sentry_grouplink
WHERE (linked_id = %s AND linked_type = 2 AND relationship = 1)
   OR (linked_id IN (SELECT id FROM sentry_commit WHERE key IN (%s) AND repository_id = %s)
       AND linked_type = 1 AND relationship = 1)

-- after, commit ids looked up first (unique (repository_id, key) index)
SELECT id FROM sentry_commit WHERE key IN (%s) AND repository_id = %s

SELECT DISTINCT group_id FROM sentry_grouplink
WHERE (linked_id = %s AND linked_type = 2 AND relationship = 1)
   OR (linked_id IN (1, 2, 3) AND linked_type = 1 AND relationship = 1)

This runs about 13M times a week in github.webhook.pull_request at ~144ms p50, roughly 485 hours of db time a week. On the db mirror a typical lookup went from ~250ms to under 1ms including the extra commit query. Example trace, the two ~138ms sentry_grouplink selects are the ones that get faster.

Things to know about the explains:

  • before: the bitmap scan on the linked_id partial index for commit resolve links has no index condition, so it returns all ~427k entries, then the heap scan touches ~14k pages and removes all but a handful with the hashed subquery. ~250ms warm, ~350ms cold, ~16k buffers
  • after: the commit lookup is ~0.4ms and the grouplink query is ~0.3-0.5ms, both under 100 buffers
  • compared results for 8 real PRs (PR links only, commit links only, both, untracked shas, empty) and they returned the same groups
  • an empty commit list just drops that side of the OR, the PR links still come back

resolved_group_ids passed the commit lookup to GroupLink as a subquery
inside an OR. Postgres can't use that as an index condition, so every
call read all commit resolve links and filtered them on the heap.
Materializing the ids makes both sides of the OR index lookups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Oct 17, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant