У нас недавно возникла перегрузка процессора.
Нам удалось определить её причину в одном запросе, который выполняется одновременно в течение нескольких часов (см. ниже).
Запускаемая задача — postmaster: после завершения всех процессов загрузка процессора снижается, пока она не будет восстановлена каждые пять минут.
SELECT "users"."id", ARRAY_AGG(ARRAY [uccm.id, c_msg.id]) AS memberships_with_unread_messages
FROM "users"
INNER JOIN "user_options" ON "user_options"."user_id" = "users"."id"
INNER JOIN user_chat_channel_memberships uccm ON uccm.user_id = users.id
INNER JOIN chat_channels cc ON cc.id = uccm.chat_channel_id
INNER JOIN chat_messages c_msg ON c_msg.chat_channel_id = uccm.chat_channel_id
LEFT OUTER JOIN chat_mentions c_mentions ON c_mentions.chat_message_id = c_msg.id
WHERE "user_options"."chat_enabled" = TRUE
AND "user_options"."chat_email_frequency" = 1
AND (users.last_seen_at < '2023-11-15 09:54:26.931723')
AND (c_msg.deleted_at IS NULL AND c_msg.user_id <> users.id)
AND (c_msg.created_at > '2023-11-08 10:09:26.931848')
AND ((uccm.last_read_message_id IS NULL OR c_msg.id > uccm.last_read_message_id) AND
(uccm.last_unread_mention_when_emailed_id IS NULL OR c_msg.id > uccm.last_unread_mention_when_emailed_id) AND
(uccm.user_id = c_mentions.user_id AND uccm.following IS true AND
cc.chatable_type = 'Category'
Может ли кто-нибудь помочь или предложить решение?
Дополнительная информация:
Работаем на версии 3.2.0.beta4-dev, но эта проблема наблюдается уже как минимум несколько месяцев.
Я работал над другим похожим запросом, и то исправление было локальным для этого запроса, поэтому оно, вероятно, не поможет здесь. Тем не менее, стоит обновиться до последней версии — там могут быть и другие оптимизации.
У одного из клиентов в чате были включены упоминания @all в двух каналах, где вместе насчитывалось 16 тысяч пользователей. Было весело!
После 19 таких упоминаний они быстро отключили эту возможность. Спустя 12 часов их (мощная) система всё ещё работала с высокой нагрузкой на процессор.
Проблема была решена удалением 320 тысяч проблемных записей из таблицы упоминаний:
delete from chat_mentions
where chat_message_id in (
(select chat_message_id
from chat_mentions
group by chat_message_id having count(*) > 100)
);
Но мы всё ещё не понимали, почему это вызывало столько проблем.
Оставалось несколько экземпляров выполнения этого запроса.
Поскольку строки уже были удалены, команда EXPLAIN не дала полезных результатов, но очевидно, что система выполняла очень тяжёлую работу. Все индексы были на месте.
Мы также наблюдали, что сообщения в чате исчезали на несколько минут, а затем появлялись снова.
В целом, я считаю, что в чате есть над чем работать, хотя мне полностью нравится направление его развития. Меня больше всего беспокоит возможность того, что чат может вызвать бесконечную перегрузку. Мы отключили возможность упоминаний, но это тоже не помогло.
Есть ли способ предотвратить повторное появление запроса, о котором я упоминал? @andrei@JammyDodger
Привет, @sok777! Спасибо, что напомнили о себе. У нас несколько инженеров уже изучают эту проблему, и мы свяжемся с вами здесь, как только появятся новости. Благодарим за терпение!
Мы удалили одно сообщение с упоминанием @all. Однако это не решило проблему. Запрос продолжает возвращаться каждые 5 минут и выполняется бесконечно долго, из-за чего образуется очередь из множества других запросов.
Как только мы отключили чат, нагрузка на процессор упала до 15%. Безумие.
Единственная причина, по которой этот запрос может выполняться долго, — это большое количество записей в таблице chat_mentions. Вы пробовали общий запрос, который я опубликовал? Возможно, упоминается не @all, а другая большая группа.
Проблемный запрос сканирует все упоминания из чатов за последние 7 дней.
Также следует завершить все существующие экземпляры этого запроса.
Да, мы их убили, но они продолжают возвращаться.
Мы проверили все упоминания выше 100, и их у нас не было. Не понимаю, почему это происходит.
Мне кажется, что проблема в самом запросе, но я могу ошибаться.
@sok777 Мне понадобится ваша небольшая помощь в этом вопросе. Я хотел бы изучить план запроса, который PostgreSQL использует на вашем сайте. Не могли бы вы выполнить этот запрос в вашей базе данных и поделиться результатами:
EXPLAIN VERBOSE SELECT "users"."id", ARRAY_AGG(ARRAY [uccm.id, c_msg.id]) AS memberships_with_unread_messages
FROM "users"
INNER JOIN "user_options" ON "user_options"."user_id" = "users"."id"
INNER JOIN "group_users" ON "group_users"."user_id" = "users"."id"
INNER JOIN "groups" ON "groups"."id" = "group_users"."group_id"
INNER JOIN user_chat_channel_memberships uccm ON uccm.user_id = users.id
INNER JOIN chat_channels cc ON cc.id = uccm.chat_channel_id
INNER JOIN chat_messages c_msg ON c_msg.chat_channel_id = uccm.chat_channel_id
LEFT OUTER JOIN chat_mentions c_mentions ON c_mentions.chat_message_id = c_msg.id
WHERE "user_options"."chat_enabled" = TRUE
AND "user_options"."chat_email_frequency" = 1
AND (users.last_seen_at < '2023-11-27 08:00:00.0000000')
AND (c_msg.deleted_at IS NULL AND c_msg.user_id <> users.id)
AND (c_msg.created_at > '2023-11-20 08:00:00.0000000')
AND ((uccm.last_read_message_id IS NULL OR c_msg.id > uccm.last_read_message_id) AND
(uccm.last_unread_mention_when_emailed_id IS NULL OR c_msg.id > uccm.last_unread_mention_when_emailed_id) AND
(
(uccm.user_id = c_mentions.user_id AND uccm.following IS true AND cc.chatable_type = 'Category') OR
(cc.chatable_type = 'DirectMessage')
)
)
GROUP BY users.id, uccm.user_id
ORDER BY "users"."id" ASC
LIMIT 1000;