summaryrefslogtreecommitdiff
path: root/app/models/merge_request.rb
diff options
context:
space:
mode:
authorYorick Peterse <yorickpeterse@gmail.com>2017-10-02 10:14:23 +0200
committerYorick Peterse <yorickpeterse@gmail.com>2017-10-02 15:31:59 +0200
commitc16b99a49c58161971d1a86613930be439385f02 (patch)
treeefe023f415f4df81b27a8c895b848a71a8c21bff /app/models/merge_request.rb
parent147c46cca195f13ef10ec8fc2db160a833121914 (diff)
downloadgitlab-ce-merge-request-notes-performance.tar.gz
Use a UNION ALL for getting merge request notesmerge-request-notes-performance
In this particular case the use of UNION ALL leads to a better query plan compared to using 1 big query that uses an OR statement to combine different data sources. See https://gitlab.com/gitlab-org/gitlab-ce/issues/38508 for more information.
Diffstat (limited to 'app/models/merge_request.rb')
-rw-r--r--app/models/merge_request.rb22
1 files changed, 14 insertions, 8 deletions
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 8d9a30397a9..15b0c24d6f2 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -552,14 +552,20 @@ class MergeRequest < ActiveRecord::Base
commits_for_notes_limit = 100
commit_ids = commit_shas.take(commits_for_notes_limit)
- Note.where(
- "(project_id = :target_project_id AND noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR" +
- "((project_id = :source_project_id OR project_id = :target_project_id) AND noteable_type = 'Commit' AND commit_id IN (:commit_ids))",
- mr_id: id,
- commit_ids: commit_ids,
- target_project_id: target_project_id,
- source_project_id: source_project_id
- )
+ commit_notes = Note
+ .except(:order)
+ .where(project_id: [source_project_id, target_project_id])
+ .where(noteable_type: 'Commit', commit_id: commit_ids)
+
+ # We're using a UNION ALL here since this results in better performance
+ # compared to using OR statements. We're using UNION ALL since the queries
+ # used won't produce any duplicates (e.g. a note for a commit can't also be
+ # a note for an MR).
+ union = Gitlab::SQL::Union
+ .new([notes, commit_notes], remove_duplicates: false)
+ .to_sql
+
+ Note.from("(#{union}) #{Note.table_name}")
end
alias_method :discussion_notes, :related_notes