Откат до 4f7f9ef87cbcd574144f657dd43b7e705d98ff8e действительно решил проблему зависших воркеров PostAlert в Sidekiq и опасений по поводу нехватки памяти (OOM): теперь несколько задач PostAlert, которые всё же попадают в очередь, выполняются за считанные секунды, а не минуты.
Привет, да, это, надеюсь, решит проблему. Я протестировал это решение на трёх форумах, и новый запрос всегда работал намного быстрее и не перегружал серверы. Спасибо за сообщение об этой проблеме. Пожалуйста, дайте знать, если вы всё ещё сталкиваетесь с трудностями.
К сожалению, даже с этими изменениями задачи PostAlert по-прежнему выполняются намного дольше, чем раньше, и полностью блокируют воркеры Sidekiq во время обработки.
(у нас более 10 млн строк пользователей, и некоторые категории отключены по умолчанию, поэтому настроено очень много отключений!)
Между тем, откат трёх последних коммитов, затрагивающих эту задачу, и перезапуск контейнера позволяют задачам выполняться без проблем.
Я только что слил ещё одну попытку улучшить производительность этой задачи:
Я протестировал это на нескольких экземплярах, и всё работало нормально, но они были меньше вашего.
Если после этого коммита ошибка всё ещё сохраняется, не могли бы вы предоставить мне отчёт EXPLAIN ANALYSE? Скрипт для его генерации:
topic = Topic.last
user_option_sql_fragment =
if SiteSetting.watched_precedence_over_muted
<<~SQL
INTERSECT
SELECT user_id FROM user_options WHERE user_options.watched_precedence_over_muted IS false
SQL
else
<<~SQL
EXCEPT
SELECT user_id FROM user_options WHERE user_options.watched_precedence_over_muted IS true
SQL
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} WHERE 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]}
)
#{user_option_sql_fragment}
SQL
sql = User.where("id IN (#{user_ids_sql})").to_sql
sql_with_index = <<SQL
EXPLAIN ANALYZE #{sql};
SQL
result = ActiveRecord::Base.connection.execute("#{sql_with_index}")
puts sql_with_index
result.each do |r|
puts r.values
end
Это поможет мне найти отсутствующий индекс или определить, какая часть этого запроса работает так медленно.