Draft: Materialize authorized projects into a CTE in ProjectsFinder

What does this MR do and why?

/api/v4/projects?membership=true&order_by=name is slow and often returns QueryCanceled. With membership=true the request is scoped to the user's authorized projects, so ProjectsFinder joins projects directly against project_authorizations and orders by projects.name. For users with many authorizations the planner can pick a slow plan for this join + sort.

This MR materializes the authorized project ids into a MATERIALIZED CTE (user_projects) and joins projects onto it, which stabilizes the plan. The change is gated behind the projects_finder_authorized_cte feature flag and only affects the membership-scoped (non_public / private_only?) path.

Related to #605822 (closed)

Query change

Before: https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/56451/commands/160672

SELECT projects.*
FROM projects
INNER JOIN project_authorizations
  ON projects.id = project_authorizations.project_id
WHERE project_authorizations.user_id = ?
  AND projects.pending_delete = FALSE
  AND projects.hidden = FALSE
ORDER BY projects.name DESC, projects.id DESC
LIMIT 20 OFFSET 0;

After: https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/56451/commands/160761

WITH user_projects AS MATERIALIZED (
  SELECT project_id
  FROM project_authorizations
  WHERE user_id = ?
)
SELECT projects.*
FROM projects
INNER JOIN user_projects ON projects.id = user_projects.project_id
WHERE projects.pending_delete = FALSE
  AND projects.hidden = FALSE
ORDER BY projects.name DESC, projects.id DESC
LIMIT 20;

Note

Query plans (before/after) from Database Lab against a high-membership user to be added before requesting database review.

Feature flag

Rollout issue: #627921 (closed)

Enable:

/chatops run feature set projects_finder_authorized_cte true

How to set up and validate locally

  1. Feature.enable(:projects_finder_authorized_cte)
  2. GET /api/v4/projects?membership=true&order_by=name
  3. Confirm results are unchanged and the emitted SQL contains user_projects AS MATERIALIZED.
Edited by Shane Maglangit

Merge request reports

Loading
Loading