FIX: more performance improvement for PostAlert job (#22487)

Simplified query based on SiteSettings to join only relevant user_options rows.
In addition, index was added to 'watched_precedence_over_muted` column in `user_options` table to speed up query
This commit is contained in:
Krzysztof Kotlarek 2023-07-13 09:02:23 +10:00 committed by GitHub
parent 4d5f9b8a21
commit bdecd697b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 50 additions and 19 deletions

View File

@ -289,7 +289,8 @@ end
#
# Indexes
#
# idx_category_users_category_id_user_id (category_id,user_id) UNIQUE
# idx_category_users_user_id_category_id (user_id,category_id) UNIQUE
# index_category_users_on_user_id_and_last_seen_at (user_id,last_seen_at)
# idx_category_users_category_id_user_id (category_id,user_id) UNIQUE
# idx_category_users_user_id_category_id (user_id,category_id) UNIQUE
# index_category_users_on_category_id_and_notification_level (category_id,notification_level)
# index_category_users_on_user_id_and_last_seen_at (user_id,last_seen_at)
#

View File

@ -582,6 +582,7 @@ end
#
# Indexes
#
# index_topic_users_on_topic_id_and_user_id (topic_id,user_id) UNIQUE
# index_topic_users_on_user_id_and_topic_id (user_id,topic_id) UNIQUE
# index_topic_users_on_topic_id_and_notification_level (topic_id,notification_level)
# index_topic_users_on_topic_id_and_user_id (topic_id,user_id) UNIQUE
# index_topic_users_on_user_id_and_topic_id (user_id,topic_id) UNIQUE
#

View File

@ -295,6 +295,7 @@ end
#
# Indexes
#
# index_user_options_on_user_id (user_id) UNIQUE
# index_user_options_on_user_id_and_default_calendar (user_id,default_calendar)
# index_user_options_on_user_id (user_id) UNIQUE
# index_user_options_on_user_id_and_default_calendar (user_id,default_calendar)
# index_user_options_on_watched_precedence_over_muted (watched_precedence_over_muted)
#

View File

@ -268,19 +268,26 @@ class PostAlerter
end
def category_or_tag_muters(topic)
user_option_condition_sql_fragment =
if SiteSetting.watched_precedence_over_muted
"uo.watched_precedence_over_muted IS false"
else
"(uo.watched_precedence_over_muted IS NULL OR uo.watched_precedence_over_muted IS false)"
end
user_ids_sql = <<~SQL
SELECT user_id FROM category_users WHERE category_id = #{topic.category_id.to_i} AND notification_level = #{CategoryUser.notification_levels[:muted]}
UNION
SELECT user_id FROM tag_users tu JOIN topic_tags tt ON tt.tag_id = tu.tag_id AND tt.topic_id = #{topic.id} AND tu.notification_level = #{TagUser.notification_levels[:muted]}
EXCEPT
SELECT user_id FROM topic_users tus WHERE tus.topic_id = #{topic.id} AND tus.notification_level = #{TopicUser.notification_levels[:watching]}
SQL
User
.where("id IN (#{user_ids_sql})")
.joins("LEFT JOIN user_options ON user_options.user_id = users.id")
.where(
"user_options.watched_precedence_over_muted IS false OR (user_options.watched_precedence_over_muted IS NULL AND #{!SiteSetting.watched_precedence_over_muted})",
)
SELECT uo.user_id FROM user_options uo
LEFT JOIN topic_users tus ON tus.user_id = uo.user_id AND tus.topic_id = #{topic.id}
LEFT JOIN category_users cu ON cu.user_id = uo.user_id AND cu.category_id = #{topic.category_id.to_i}
LEFT JOIN tag_users tu ON tu.user_id = uo.user_id
JOIN topic_tags tt ON tt.tag_id = tu.tag_id AND tt.topic_id = #{topic.id}
WHERE
(tus.id IS NULL OR tus.notification_level != #{TopicUser.notification_levels[:watching]})
AND (cu.notification_level = #{CategoryUser.notification_levels[:muted]} OR tu.notification_level = #{TagUser.notification_levels[:muted]})
AND #{user_option_condition_sql_fragment}
SQL
User.where("id IN (#{user_ids_sql})")
end
def notify_first_post_watchers(post, user_ids, notified = nil)

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddWatchedPrecedenceOverMutedIndexToUserOptions < ActiveRecord::Migration[7.0]
def change
add_index :user_options, :watched_precedence_over_muted
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
#
class AddTopicIdNotificationLevelIndexToTopicUsers < ActiveRecord::Migration[7.0]
def change
add_index :topic_users, %i[topic_id notification_level]
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddCategoryIdNotificationLevelIndexToCategoryUsers < ActiveRecord::Migration[7.0]
def change
add_index :category_users, %i[category_id notification_level]
end
end