Filter issues / merge request fuzzy search those comments
What does this MR do?
Filter issues / merge requests fuzzy search those comments.
Are there points in the code the reviewer needs to double check?
- SQL performance
Test data
Data
gitlabhq_development=# SELECT COUNT(*) FROM issues; count ------- 12333gitlabhq_development=# SELECT COUNT(*) FROM notes; count
999
Query without project
The following is EXPLAIN ANALYSE output made by Issue.full_search_with_comments("foo bar")
Query
EXPLAIN ANALYZE SELECT "issues".*
FROM "issues"
WHERE "issues"."deleted_at" IS NULL
AND (issues.id IN
(SELECT "issues"."id"
FROM "issues"
WHERE "issues"."deleted_at" IS NULL
AND ("issues"."title" ILIKE '%foo%'
AND "issues"."title" ILIKE '%bar%'
OR "issues"."description" ILIKE '%foo%'
AND "issues"."description" ILIKE '%bar%')
UNION SELECT "notes"."noteable_id"
FROM "notes"
WHERE "notes"."noteable_type" = 'Issue'
AND ("notes"."note" ILIKE '%foo%'
AND "notes"."note" ILIKE '%bar%')))
ORDER BY "issues"."id" DESC;
Query plan
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=108.73..108.74 rows=2 width=347) (actual time=0.105..0.105 rows=0 loops=1)
Sort Key: issues.id DESC
Sort Method: quicksort Memory: 25kB
-> Nested Loop (cost=92.35..108.72 rows=2 width=347) (actual time=0.097..0.097 rows=0 loops=1)
-> Unique (cost=92.07..92.08 rows=2 width=4) (actual time=0.097..0.097 rows=0 loops=1)
-> Sort (cost=92.07..92.07 rows=2 width=4) (actual time=0.097..0.097 rows=0 loops=1)
Sort Key: issues_1.id
Sort Method: quicksort Memory: 25kB
-> Append (cost=48.00..92.06 rows=2 width=4) (actual time=0.089..0.089 rows=0 loops=1)
-> Bitmap Heap Scan on issues issues_1 (cost=48.00..52.02 rows=1 width=4) (actual time=0.040..0.040 rows=0 loops=1)
Recheck Cond: ((((title)::text ~~* '%foo%'::text) AND ((title)::text ~~* '%bar%'::text)) OR ((description ~~* '%foo%'::text) AND (description ~~* '%bar%'::text)))
Filter: (deleted_at IS NULL)
-> BitmapOr (cost=48.00..48.00 rows=1 width=0) (actual time=0.039..0.039 rows=0 loops=1)
-> Bitmap Index Scan on index_issues_on_title_trigram (cost=0.00..24.00 rows=1 width=0) (actual time=0.022..0.022 rows=0 loops=1)
Index Cond: (((title)::text ~~* '%foo%'::text) AND ((title)::text ~~* '%bar%'::text))
-> Bitmap Index Scan on index_issues_on_description_trigram (cost=0.00..24.00 rows=1 width=0) (actual time=0.014..0.014 rows=0 loops=1)
Index Cond: ((description ~~* '%foo%'::text) AND (description ~~* '%bar%'::text))
-> Bitmap Heap Scan on notes (cost=36.00..40.02 rows=1 width=4) (actual time=0.049..0.049 rows=0 loops=1)
Recheck Cond: ((note ~~* '%foo%'::text) AND (note ~~* '%bar%'::text))
Filter: ((noteable_type)::text = 'Issue'::text)
Rows Removed by Filter: 1
Heap Blocks: exact=1
-> Bitmap Index Scan on index_notes_on_note_trigram (cost=0.00..36.00 rows=1 width=0) (actual time=0.034..0.034 rows=1 loops=1)
Index Cond: ((note ~~* '%foo%'::text) AND (note ~~* '%bar%'::text))
-> Index Scan using issues_pkey on issues (cost=0.29..8.30 rows=1 width=347) (never executed)
Index Cond: (id = issues_1.id)
Filter: (deleted_at IS NULL)
Planning time: 1.222 ms
Execution time: 0.480 ms
Query with project
The following is EXPLAIN ANALYSE output made by IssuesFinder.new(user, params).execute
=> #<IssuesFinder:0x007f9a9ea0c248
@current_user=#<User id:1 @root>,
@params={"project_id"=>1, "search"=>"foo bar"}>
Query
SELECT "issues".* FROM "issues" WHERE "issues"."deleted_at" IS NULL AND (issues.id IN (SELECT "issues"."id" FROM "issues" WHERE "issues"."deleted_at" IS NULL AND ("issues"."title" ILIKE '%foo%' AND "issues"."title" ILIKE '%bar%' OR "issues"."description" ILIKE '%foo%' AND "issues"."description" ILIKE '%bar%')
UNION
SELECT "notes"."noteable_id" FROM "notes" WHERE "notes"."noteable_type" = 'Issue' AND ("notes"."note" ILIKE '%foo%' AND "notes"."note" ILIKE '%bar%'))) AND "issues"."project_id" = 1 ORDER BY "issues"."id" DESC
Query plan
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=120.74..120.74 rows=1 width=347) (actual time=0.204..0.205 rows=4 loops=1)
Sort Key: issues.id DESC
Sort Method: quicksort Memory: 26kB
-> Nested Loop (cost=104.35..120.73 rows=1 width=347) (actual time=0.169..0.186 rows=4 loops=1)
-> Unique (cost=104.07..104.08 rows=2 width=4) (actual time=0.156..0.158 rows=4 loops=1)
-> Sort (cost=104.07..104.07 rows=2 width=4) (actual time=0.155..0.155 rows=4 loops=1)
Sort Key: issues_1.id
Sort Method: quicksort Memory: 25kB
-> Append (cost=52.00..104.06 rows=2 width=4) (actual time=0.075..0.142 rows=4 loops=1)
-> Bitmap Heap Scan on issues issues_1 (cost=52.00..56.02 rows=1 width=4) (actual time=0.075..0.083 rows=4 loops=1)
Recheck Cond: ((((title)::text ~~* '%foo%'::text) AND ((title)::text ~~* '%bar%'::text)) OR ((description ~~* '%foo%'::text) AND (description ~~* '%bar%'::text)))
Filter: (deleted_at IS NULL)
Heap Blocks: exact=2
-> BitmapOr (cost=52.00..52.00 rows=1 width=0) (actual time=0.059..0.059 rows=0 loops=1)
-> Bitmap Index Scan on index_issues_on_title_trigram (cost=0.00..28.00 rows=1 width=0) (actual time=0.045..0.045 rows=4 loops=1)
Index Cond: (((title)::text ~~* '%foo%'::text) AND ((title)::text ~~* '%bar%'::text))
-> Bitmap Index Scan on index_issues_on_description_trigram (cost=0.00..24.00 rows=1 width=0) (actual time=0.014..0.014 rows=0 loops=1)
Index Cond: ((description ~~* '%foo%'::text) AND (description ~~* '%bar%'::text))
-> Bitmap Heap Scan on notes (cost=44.00..48.02 rows=1 width=4) (actual time=0.058..0.058 rows=0 loops=1)
Recheck Cond: ((note ~~* '%foo%'::text) AND (note ~~* '%bar%'::text))
Filter: ((noteable_type)::text = 'Issue'::text)
Rows Removed by Filter: 1
Heap Blocks: exact=1
-> Bitmap Index Scan on index_notes_on_note_trigram (cost=0.00..44.00 rows=1 width=0) (actual time=0.044..0.044 rows=1 loops=1)
Index Cond: ((note ~~* '%foo%'::text) AND (note ~~* '%bar%'::text))
-> Index Scan using issues_pkey on issues (cost=0.29..8.30 rows=1 width=347) (actual time=0.004..0.004 rows=1 loops=4)
Index Cond: (id = issues_1.id)
Filter: ((deleted_at IS NULL) AND (project_id = 1))
Planning time: 1.816 ms
Execution time: 0.330 ms
Why was this MR needed?
Currently those searches the issue title and description, but not comments.
Does this MR meet the acceptance criteria?
-
Changelog entry added, if necessary -
Documentation created/updated -
API support added -
Tests added for this feature/bug - Review
-
Has been reviewed by UX -
Has been reviewed by Frontend -
Has been reviewed by Backend -
Has been reviewed by Database
-
-
Conform by the merge request performance guides -
Conform by the style guides -
Squashed related commits together
What are the relevant issue numbers?
Closes #20872 (moved), #2201 (moved)
Edited by Hiroyuki Sato