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(
current_user,
topic_scope.distinct(false).pluck(:id),
topic_scope.pluck(:id),
type: "dismiss_topics"
).perform!
@ -1245,11 +1245,7 @@ class TopicsController < ApplicationController
if inbox = params[:private_message_inbox]
filter = private_message_filter(topic_query, inbox)
topic_query.options[:limit] = false
topic_query
.filter_private_messages_unread(current_user, filter)
.distinct(false)
.pluck(:id)
topics = topic_query.filter_private_messages_unread(current_user, filter)
else
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"
@ -1268,9 +1264,9 @@ class TopicsController < ApplicationController
if params[:tag_name].present?
topics = topics.joins(:tags).where("tags.name": params[:tag_name])
end
topics.pluck(:id)
end
topics.pluck(:id)
end
def private_message_filter(topic_query, inbox)

View File

@ -145,18 +145,25 @@ class TopicQuery
elsif type == :all
group_ids = group_with_messages_ids(user)
result = result.joins(<<~SQL)
LEFT JOIN topic_allowed_users tau
ON tau.topic_id = topics.id
AND tau.user_id = #{user.id.to_i}
LEFT JOIN topic_allowed_groups tag
ON tag.topic_id = topics.id
#{group_ids.present? ? "AND tag.group_id IN (#{group_ids.join(",")})" : ""}
SQL
result = result
.where("tag.topic_id IS NOT NULL OR tau.topic_id IS NOT NULL")
.distinct
result =
if group_ids.present?
result.where(<<~SQL)
topics.id IN (
SELECT topic_id
FROM topic_allowed_users
WHERE user_id = #{user.id.to_i}
UNION ALL
SELECT topic_id FROM topic_allowed_groups
WHERE group_id IN (#{group_ids.join(",")})
)
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
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.
group_ids = group_with_messages_ids(user)
list = list.joins(<<~SQL)
LEFT JOIN group_archived_messages gm
ON gm.topic_id = topics.id
#{group_ids.present? ? "AND gm.group_id IN (#{group_ids.join(",")})" : ""}
LEFT JOIN user_archived_messages um
ON um.user_id = #{user.id.to_i}
AND um.topic_id = topics.id
SQL
if group_ids.present?
list = list.joins(<<~SQL)
LEFT JOIN group_archived_messages gm
ON gm.topic_id = topics.id
AND gm.group_id IN (#{group_ids.join(",")})
LEFT JOIN user_archived_messages um
ON um.user_id = #{user.id.to_i}
AND um.topic_id = topics.id
SQL
list =
if archived
list.where("um.user_id IS NOT NULL OR gm.topic_id IS NOT NULL")
else
list.where("um.user_id IS NULL AND gm.topic_id IS NULL")
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
def not_archived(list, user)