Skip to content

Skip projects filter on issues search

Jan Provaznik requested to merge jprovazn-search-issues into master

What does this MR do?

It skips project filter when searching for issues unless a project context is used, very similar to !15955 (merged).

Are there points in the code the reviewer needs to double check?

Double check it's safe to remove projects filter if project context is not used.

Why was this MR needed?

Global search query may be slow - #40540 (closed). This patch speeds up searching of issues which is part of the global search. Search query without the patch https://gitlab.com/snippets/1690165:

 Planning time: 9.581 ms
 Execution time: 1600.658 ms


SELECT COUNT(*)
FROM "issues"
INNER JOIN "projects" ON "projects"."id" = "issues"."project_id"
LEFT JOIN project_features ON projects.id = project_features.project_id
WHERE "issues"."deleted_at" IS NULL
  AND ( issues.confidential IS NOT TRUE
       OR (issues.confidential = TRUE
           AND (issues.author_id = 1642716
                OR EXISTS
                  (SELECT TRUE
                   FROM issue_assignees
                   WHERE user_id = 1642716
                     AND issue_id = issues.id)
                OR issues.project_id IN
                  (SELECT "projects"."id"
                   FROM "projects"
                   INNER JOIN "project_authorizations" ON "projects"."id" = "project_authorizations"."project_id"
                   WHERE "project_authorizations"."user_id" = 1642716
                     AND (project_authorizations.access_level >= 20)))))
  AND (EXISTS
         (SELECT 1
          FROM "project_authorizations"
          WHERE "project_authorizations"."user_id" = 1642716
            AND (project_authorizations.project_id = projects.id))
       OR projects.visibility_level IN (10,
                                        20))
  AND "projects"."id" IN
    (SELECT "issues"."project_id"
     FROM "issues"
     WHERE "issues"."deleted_at" IS NULL
       AND ( issues.confidential IS NOT TRUE
            OR (issues.confidential = TRUE
                AND (issues.author_id = 49
                     OR EXISTS
                       (SELECT TRUE
                        FROM issue_assignees
                        WHERE user_id = 49
                          AND issue_id = issues.id)
                     OR issues.project_id IN
                       (SELECT "projects"."id"
                        FROM "projects"
                        INNER JOIN "project_authorizations" ON "projects"."id" = "project_authorizations"."project_id"
                        WHERE "project_authorizations"."user_id" = 49
                          AND (project_authorizations.access_level >= 20))))))
  AND ("project_features"."issues_access_level" IN (NULL,
                                                    20)
       OR ("project_features"."issues_access_level" = 10
           AND EXISTS
             (SELECT 1
              FROM "project_authorizations"
              WHERE "project_authorizations"."user_id" = 49
                AND (project_authorizations.project_id = projects.id))))
  AND "issues"."project_id" IN
    (SELECT "projects"."id"
     FROM "projects"
     WHERE (EXISTS
              (SELECT 1
               FROM "project_authorizations"
               WHERE "project_authorizations"."user_id" = 49
                 AND (project_authorizations.project_id = projects.id))
            OR projects.visibility_level IN (10,
                                             20)))
  AND ("issues"."title" ILIKE '%test1%'
       OR "issues"."description" ILIKE '%test1%')

Search query with this patch - https://gitlab.com/snippets/1690161:

 Planning time: 3.909 ms
 Execution time: 936.138 ms


SELECT COUNT(*)
FROM "issues"
INNER JOIN "projects" ON "projects"."id" = "issues"."project_id"
LEFT JOIN project_features ON projects.id = project_features.project_id
WHERE "issues"."deleted_at" IS NULL
  AND ( issues.confidential IS NOT TRUE
       OR (issues.confidential = TRUE
           AND (issues.author_id = 1642716
                OR EXISTS
                  (SELECT TRUE
                   FROM issue_assignees
                   WHERE user_id = 1642716
                     AND issue_id = issues.id)
                OR issues.project_id IN
                  (SELECT "projects"."id"
                   FROM "projects"
                   INNER JOIN "project_authorizations" ON "projects"."id" = "project_authorizations"."project_id"
                   WHERE "project_authorizations"."user_id" = 1642716
                     AND (project_authorizations.access_level >= 20)))))
  AND (EXISTS
         (SELECT 1
          FROM "project_authorizations"
          WHERE "project_authorizations"."user_id" = 1642716
            AND (project_authorizations.project_id = projects.id))
       OR projects.visibility_level IN (10,
                                        20))
  AND "projects"."id" IN
    (SELECT "issues"."project_id"
     FROM "issues"
     WHERE "issues"."deleted_at" IS NULL
       AND ( issues.confidential IS NOT TRUE
            OR (issues.confidential = TRUE
                AND (issues.author_id = 49
                     OR EXISTS
                       (SELECT TRUE
                        FROM issue_assignees
                        WHERE user_id = 49
                          AND issue_id = issues.id)
                     OR issues.project_id IN
                       (SELECT "projects"."id"
                        FROM "projects"
                        INNER JOIN "project_authorizations" ON "projects"."id" = "project_authorizations"."project_id"
                        WHERE "project_authorizations"."user_id" = 49
                          AND (project_authorizations.access_level >= 20))))))
  AND ("project_features"."issues_access_level" IN (NULL,
                                                    20)
       OR ("project_features"."issues_access_level" = 10
           AND EXISTS
             (SELECT 1
              FROM "project_authorizations"
              WHERE "project_authorizations"."user_id" = 49
                AND (project_authorizations.project_id = projects.id))))
  AND ("issues"."title" ILIKE '%test1%'
       OR "issues"."description" ILIKE '%test1%')

So the following extra filter is now removed by default:

<   AND "issues"."project_id" IN
<     (SELECT "projects"."id"
<      FROM "projects"
<      WHERE (EXISTS
<               (SELECT 1
<                FROM "project_authorizations"
<                WHERE "project_authorizations"."user_id" = 49
<                  AND (project_authorizations.project_id = projects.id))
<             OR projects.visibility_level IN (10,
<                                              20)))

Does this MR meet the acceptance criteria?

What are the relevant issue numbers?

#40540 (closed)

Edited by Jan Provaznik

Merge request reports