Partially revert "PERF: Improve query performance all inbox private messages. (#14304)" (#14344)

This partially reverts commit ddb458343d.

Seeing performance degrade on larger sites so back to drawing board on
this one. Instead of the DISTINCT LEFT JOIN, we switch back to
IN(subquery).
This commit is contained in:
Alan Guo Xiang Tan 2021-09-15 11:32:10 +08:00 committed by GitHub
parent ddb458343d
commit 27bad28c53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 30 deletions

View File

@ -973,7 +973,7 @@ class TopicsController < ApplicationController
topic_ids = TopicsBulkAction.new( topic_ids = TopicsBulkAction.new(
current_user, current_user,
topic_scope.distinct(false).pluck(:id), topic_scope.pluck(:id),
type: "dismiss_topics" type: "dismiss_topics"
).perform! ).perform!
@ -1245,11 +1245,7 @@ class TopicsController < ApplicationController
if inbox = params[:private_message_inbox] if inbox = params[:private_message_inbox]
filter = private_message_filter(topic_query, inbox) filter = private_message_filter(topic_query, inbox)
topic_query.options[:limit] = false topic_query.options[:limit] = false
topics = topic_query.filter_private_messages_unread(current_user, filter)
topic_query
.filter_private_messages_unread(current_user, filter)
.distinct(false)
.pluck(:id)
else else
topics = TopicQuery.unread_filter(topic_query.joined_topic_user, staff: guardian.is_staff?).listable_topics topics = TopicQuery.unread_filter(topic_query.joined_topic_user, staff: guardian.is_staff?).listable_topics
topics = TopicQuery.tracked_filter(topics, current_user.id) if params[:tracked].to_s == "true" topics = TopicQuery.tracked_filter(topics, current_user.id) if params[:tracked].to_s == "true"
@ -1268,9 +1264,9 @@ class TopicsController < ApplicationController
if params[:tag_name].present? if params[:tag_name].present?
topics = topics.joins(:tags).where("tags.name": params[:tag_name]) topics = topics.joins(:tags).where("tags.name": params[:tag_name])
end end
topics.pluck(:id)
end end
topics.pluck(:id)
end end
def private_message_filter(topic_query, inbox) def private_message_filter(topic_query, inbox)

View File

@ -145,18 +145,25 @@ class TopicQuery
elsif type == :all elsif type == :all
group_ids = group_with_messages_ids(user) group_ids = group_with_messages_ids(user)
result = result.joins(<<~SQL) result =
LEFT JOIN topic_allowed_users tau if group_ids.present?
ON tau.topic_id = topics.id result.where(<<~SQL)
AND tau.user_id = #{user.id.to_i} topics.id IN (
LEFT JOIN topic_allowed_groups tag SELECT topic_id
ON tag.topic_id = topics.id FROM topic_allowed_users
#{group_ids.present? ? "AND tag.group_id IN (#{group_ids.join(",")})" : ""} WHERE user_id = #{user.id.to_i}
SQL UNION ALL
SELECT topic_id FROM topic_allowed_groups
result = result WHERE group_id IN (#{group_ids.join(",")})
.where("tag.topic_id IS NOT NULL OR tau.topic_id IS NOT NULL") )
.distinct SQL
else
result.joins(<<~SQL)
INNER JOIN topic_allowed_users tau
ON tau.topic_id = topics.id
AND tau.user_id = #{user.id.to_i}
SQL
end
end end
result = result.joins("LEFT OUTER JOIN topic_users AS tu ON (topics.id = tu.topic_id AND tu.user_id = #{user.id.to_i})") result = result.joins("LEFT OUTER JOIN topic_users AS tu ON (topics.id = tu.topic_id AND tu.user_id = #{user.id.to_i})")
@ -238,23 +245,30 @@ class TopicQuery
# query here as it can easily lead to an inefficient query. # query here as it can easily lead to an inefficient query.
group_ids = group_with_messages_ids(user) group_ids = group_with_messages_ids(user)
list = list.joins(<<~SQL) if group_ids.present?
LEFT JOIN group_archived_messages gm list = list.joins(<<~SQL)
ON gm.topic_id = topics.id LEFT JOIN group_archived_messages gm
#{group_ids.present? ? "AND gm.group_id IN (#{group_ids.join(",")})" : ""} ON gm.topic_id = topics.id
LEFT JOIN user_archived_messages um AND gm.group_id IN (#{group_ids.join(",")})
ON um.user_id = #{user.id.to_i} LEFT JOIN user_archived_messages um
AND um.topic_id = topics.id ON um.user_id = #{user.id.to_i}
SQL AND um.topic_id = topics.id
SQL
list =
if archived if archived
list.where("um.user_id IS NOT NULL OR gm.topic_id IS NOT NULL") list.where("um.user_id IS NOT NULL OR gm.topic_id IS NOT NULL")
else else
list.where("um.user_id IS NULL AND gm.topic_id IS NULL") list.where("um.user_id IS NULL AND gm.topic_id IS NULL")
end end
else
list = list.joins(<<~SQL)
LEFT JOIN user_archived_messages um
ON um.user_id = #{user.id.to_i}
AND um.topic_id = topics.id
SQL
list list.where("um.user_id IS #{archived ? "NOT NULL" : "NULL"}")
end
end end
def not_archived(list, user) def not_archived(list, user)