Skip to content

Optimize queries in MergeRequestsComplianceFinder

What does this MR do?

This MR tries to optimize the queries inside MergeRequestsComplianceFinder class.

Changes:

  • Adds missing associations that are required for preload.
  • Tries to make the "LATERAL" query more readable (while maintaining the same logic)
  • Prevents loading of all MRs into memory at once, which were then later paginated using Kaminari.paginate_array. The pagination is now done at database level itself using the normal LIMIT OFFSET approach, which helps limit the no of MRs loaded into memory.

Queries

Old query (with lateral) - this gets only events, we had to fetch MRs again using a new query:

explain SELECT projects.id, events.target_id as merge_request_id FROM (SELECT "projects".* FROM "projects" WHERE "projects"."namespace_id" IN (WITH RECURSIVE "base_and_descendants" AS ((SELECT "namespaces".* FROM "namespaces" WHERE "namespaces"."type" = 'Group' AND "namespaces"."id" = 9970)
UNION
(SELECT "namespaces".* FROM "namespaces", "base_and_descendants" WHERE "namespaces"."type" = 'Group' AND "namespaces"."parent_id" = "base_and_descendants"."id")) SELECT "namespaces"."id" FROM "base_and_descendants" AS "namespaces")) projects JOIN LATERAL (SELECT "events"."created_at", "events"."target_id" FROM "events" WHERE (projects.id = project_id) AND "events"."action" = 7 ORDER BY "events"."id" DESC LIMIT 1) events ON true ORDER BY events.created_at DESC

Plan

New query (with lateral, cte and ordering MergeRequests on array_position) - this includes fetching MergeRequests too, so we do not have to fire another query like we had been doing till now:

explain WITH "ordered_events_cte" AS (SELECT events.target_id as target_id FROM "projects" JOIN LATERAL (SELECT "events"."created_at", "events"."target_id" FROM "events" WHERE (projects.id = project_id) AND "events"."action" = 7 ORDER BY "events"."id" DESC LIMIT 1) events ON true WHERE "projects"."namespace_id" IN (WITH RECURSIVE "base_and_descendants" AS ((SELECT "namespaces".* FROM "namespaces" WHERE "namespaces"."type" = 'Group' AND "namespaces"."id" = 9970)
UNION
(SELECT "namespaces".* FROM "namespaces", "base_and_descendants" WHERE "namespaces"."type" = 'Group' AND "namespaces"."parent_id" = "base_and_descendants"."id")) SELECT "namespaces"."id" FROM "base_and_descendants" AS "namespaces") ORDER BY events.created_at DESC) SELECT "merge_requests".* FROM "merge_requests" INNER JOIN "ordered_events_cte" ON "merge_requests"."id" = "ordered_events_cte"."target_id" ORDER BY array_position(ARRAY(SELECT target_id FROM ordered_events_cte), merge_requests.id)

Plan

Screenshots

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • Label as security and @ mention @gitlab-com/gl-security/appsec
  • The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • Security reports checked/validated by a reviewer from the AppSec team

Merge request reports