From c16b99a49c58161971d1a86613930be439385f02 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Mon, 2 Oct 2017 10:14:23 +0200 Subject: Use a UNION ALL for getting merge request notes 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. --- app/models/merge_request.rb | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'app/models/merge_request.rb') 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 -- cgit v1.2.1