Запрос вызывает нагрузку на ЦП 400%

У нас недавно возникла перегрузка процессора.
Нам удалось определить её причину в одном запросе, который выполняется одновременно в течение нескольких часов (см. ниже).
Запускаемая задача — 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, но эта проблема наблюдается уже как минимум несколько месяцев.
  • Вот список установленных плагинов:

Спасибо!

2 лайка

@andrei недавно занимался оптимизацией запросов чата, эта проблема сохраняется после обновления до последней версии?

4 лайка

Я работал над другим похожим запросом, и то исправление было локальным для этого запроса, поэтому оно, вероятно, не поможет здесь. Тем не менее, стоит обновиться до последней версии — там могут быть и другие оптимизации.

2 лайка

Мы используем последнюю версию Indeed.

Думаю, это была проблема чата, связанная с запросом. Можно ли что-то настроить в параметрах, чтобы исправить это?

1 лайк

У одного из клиентов в чате были включены упоминания @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 не дала полезных результатов, но очевидно, что система выполняла очень тяжёлую работу. Все индексы были на месте.

1 лайк

Кажется, кто-то упоминал, что запрос вчера также вызывал высокую нагрузку:

2 лайка

Спасибо — мне стоит научиться эффективнее искать на этом форуме.

1 лайк

Это не помогло нам решить проблему.

Мы также наблюдали, что сообщения в чате исчезали на несколько минут, а затем появлялись снова.

В целом, я считаю, что в чате есть над чем работать, хотя мне полностью нравится направление его развития. Меня больше всего беспокоит возможность того, что чат может вызвать бесконечную перегрузку. Мы отключили возможность упоминаний, но это тоже не помогло.

Есть ли способ предотвратить повторное появление запроса, о котором я упоминал? @andrei @JammyDodger

Заранее спасибо.

Привет, @sok777! Спасибо, что напомнили о себе. У нас несколько инженеров уже изучают эту проблему, и мы свяжемся с вами здесь, как только появятся новости. Благодарим за терпение!

2 лайка

Один из работающих приёмов: Администрирование → Настройка → Просматриваемые слова, и добавьте оба упоминания в список «Цензура».

то есть «all» и «here» с префиксом @?

Спасибо!

1 лайк

Отлично. Спасибо!

1 лайк

Быстрое обновление @lindsey @RGJ

Мы удалили одно сообщение с упоминанием @all. Однако это не решило проблему. Запрос продолжает возвращаться каждые 5 минут и выполняется бесконечно долго, из-за чего образуется очередь из множества других запросов.
Как только мы отключили чат, нагрузка на процессор упала до 15%. Безумие.

Вам нужно зайти в базу данных и удалить записи о упоминаниях

psql: delete from chat_mentions where chat_message_id = X
где X — это ID сообщения, которое вы удалили.

Более универсальный запрос описан в моём сообщении здесь, откорректируйте число по своему усмотрению.

1 лайк

Да, мы уже пробовали это.

Для справки, вот наши показатели:

users: 239251
chat_channels: 2864
chat_drafts: 205
chat_mentions: 155527 → 7500~
chat_messages: 390453
chat_threads: 25131
chat_message_reactions: 5993
user_chat_channel_memberships: 158480

1 лайк

Единственная причина, по которой этот запрос может выполняться долго, — это большое количество записей в таблице chat_mentions. Вы пробовали общий запрос, который я опубликовал? Возможно, упоминается не @all, а другая большая группа.

Проблемный запрос сканирует все упоминания из чатов за последние 7 дней.

Также следует завершить все существующие экземпляры этого запроса.

Да, мы их убили, но они продолжают возвращаться.
Мы проверили все упоминания выше 100, и их у нас не было. Не понимаю, почему это происходит.
Мне кажется, что проблема в самом запросе, но я могу ошибаться.

1 лайк

Этот запрос, вероятно, выполняется медленно, даже при небольшом количестве упоминаний. Я займусь его исправлением.

2 лайка

Отлично. С радостью продолжим поддержку с нашей точки зрения!

2 лайка

@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;
1 лайк