Skip to content

Batch load Project#open_merge_requests_count

What does this MR do and why?

This gives Project#open_merge_request_count the same treatment as Project#open_issues_count to batch load projects while also maintaining the redis cache.

Part of #214037

Screenshots or screen recordings

Screenshots are required for UI changes, and strongly recommended for all other merge requests.

How to set up and validate locally

  1. Change the expected count to 3 in the N+1 test at spec/features/dashboard/projects_spec.rb:255.
  2. Run the N+1 test; observe that it passes.
  3. Revert the helper method to what it was before
  4. Run the N+1 test; observe that it fails with a merge request query being the offender

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Database

Raw query example

Picked out a few project IDs from the project dashboard on GitLab.com with lots stars and lots of open MRs.

SELECT
    COUNT(*) AS count_all,
    "merge_requests"."target_project_id" AS merge_requests_target_project_id
FROM
    "merge_requests"
WHERE ("merge_requests"."state_id" IN (1))
    AND "merge_requests"."target_project_id" IN (13083, 7764, 17599543, 250833, 74823, 20699)
GROUP BY
    "merge_requests"."target_project_id"

Query plan

postgres.ai link (internal)

 Aggregate  (cost=0.57..284.43 rows=3873 width=12) (actual time=3.415..3.933 rows=5 loops=1)
   Group Key: merge_requests.target_project_id
   Buffers: shared hit=3375
   I/O Timings: read=0.000 write=0.000
   ->  Index Only Scan using idx_mrs_on_target_id_and_created_at_and_state_id on public.merge_requests  (cost=0.57..226.22 rows=3895 width=4) (actual time=0.101..3.624 rows=2545 loops=1)
         Index Cond: ((merge_requests.target_project_id = ANY ('{13083,7764,17599543,250833,74823,20699}'::integer[])) AND (merge_requests.state_id = 1))
         Heap Fetches: 1478
         Buffers: shared hit=3375
         I/O Timings: read=0.000 write=0.000

Note that this index' name is out of order, the index is:

CREATE INDEX idx_mrs_on_target_id_and_created_at_and_state_id ON merge_requests USING btree (target_project_id, state_id, created_at, id);
Edited by Hordur Freyr Yngvason

Merge request reports