Graphql N+1 Triage: getProjectsMergeRequestNotes
Summary
getProjectsMergeRequestNotes ranked among the top N+1 candidates on gitlab.com, based on 24 hours of production log data.
It's estimated to cost 305.1 avoidable queries per minute.
See https://gitlab.com/groups/gitlab-org/-/epics/23614 for how this list was built and the method to follow.
Numbers
| Metric | Value |
|---|---|
| Requests in 24h | 22,831 |
| N+1 risk | 0.98 |
| p95 queries on main replica | 1232 |
| p95 DB duration (s) | 3.589 |
| Estimated savings per minute | 305.1 |
Where the query comes from
No .graphql file in gitlab-org/gitlab defines this operation, so it comes from an external client (IDE extension, CLI, or a third-party API user). Reconstruct the selection from json.graphql.used_fields in Kibana.
Primary type read, inferred from the operation name: MergeRequest. Owning group: group::code review.
What to do
- Find the query source: the
.graphqlfile in the repo, orjson.graphql.used_fieldsin Kibana for external clients. - Write a throwaway request spec, run it against a small and a larger page, and record queries with
ActiveRecord::QueryRecorder.new(skip_cached: false). - Fix per-row growth with lookahead preloads,
BatchLoader::GraphQL, or a policy preloader inbefore_connection_authorization. - Add a permanent N+1 spec that asserts query counts don't grow with page size.
- After deploy, confirm the savings estimate dropped in the Lens table.
Acceptance criteria
- Per-row queries identified and listed in this issue.
- Fix merged.
- Permanent N+1 spec added.
- Savings in the Lens table dropped after deploy, or this issue is closed with an explanation of why the spread is fixed cost.
Edited by Eduardo Bonet