Query che causa 400% CPU Load

Abbiamo recentemente avuto un sovraccarico della CPU.
Siamo riusciti a individuarlo in un’unica query che continua a essere eseguita contemporaneamente per ore (vedi sotto).
L’attività in esecuzione è postmaster: una volta che tutte vengono interrotte, la CPU si riduce fino a quando non viene ricostruita ogni cinque minuti.

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’

Qualcuno può aiutare o suggerire una soluzione?

Ulteriori informazioni:

  • in esecuzione 3.2.0.beta4-dev, ma questo accade da almeno qualche mese
  • Ecco un elenco dei plugin che abbiamo installato:

Grazie!

2 Mi Piace

@andrei ha lavorato di recente all’ottimizzazione delle query di chat, succede ancora dopo l’aggiornamento all’ultima versione?

4 Mi Piace

Ho lavorato su un’altra query simile e quella correzione era locale a quella query, quindi probabilmente non aiuterà qui. Tuttavia, vale la pena aggiornare all’ultima versione, potrebbero esserci altre ottimizzazioni.

2 Mi Piace

Siamo sull’ultima versione, in effetti.

Suppongo sia stato un problema di chat dovuto alla query. C’è qualcosa che possiamo modificare dalle impostazioni per risolvere il problema?

1 Mi Piace

Abbiamo avuto un cliente che ha attivato le menzioni @all nella chat, con due canali da 16k utenti. È stato divertente!
Dopo 19 menzioni a tutti, l’hanno disattivata rapidamente. 12 ore dopo il loro (potente) sistema era ancora a pieno carico della CPU.

Il problema è stato risolto eliminando i 320k record incriminati dalla tabella delle menzioni

delete from chat_mentions
where chat_message_id in (
  (select chat_message_id
   from chat_mentions
   group by chat_message_id having count(*) > 100)
);

ma eravamo ancora perplessi sul perché questo stesse causando così tanti problemi.
C’erano un certo numero di istanze di questa query ancora in esecuzione.

Poiché le righe erano già state eliminate, un explain non ha fornito buoni risultati, ma è chiaro che stava facendo un lavoro pesante. Tutti gli indici sono presenti.

1 Mi Piace

Penso che qualcuno abbia menzionato che anche la query è stata intensiva ieri:

2 Mi Piace

Grazie, dovrei imparare a cercare in questo forum in modo più efficace.

1 Mi Piace

Non ha risolto il problema per noi.

Abbiamo anche visto messaggi di chat scomparire per alcuni minuti prima di riapparire.

In generale, penso che ci sia molto da migliorare nella chat, anche se mi piace totalmente la direzione in cui sta andando. La mia preoccupazione principale è come una chat possa essenzialmente causare un sovraccarico che non si ferma. Abbiamo disattivato la possibilità di menzionare e nemmeno questo ha funzionato.

C’è un modo per impedire che la query che ho menzionato ritorni? @andrei @JammyDodger

Grazie in anticipo

Ciao @sok777, grazie per il tuo follow-up — abbiamo alcuni ingegneri che stanno esaminando la questione e ti aggiorneremo qui non appena avremo novità. Apprezziamo la tua pazienza nel frattempo!

2 Mi Piace

Un trucco che funziona bene è Amministratore - Personalizza - Parole monitorate e aggiungere entrambe le menzioni all’elenco “Censura”.

quindi ‘tutti’ e ‘qui’ con un prefisso di @?

Grazie!

1 Mi Piace

Ottimo. Grazie!

1 Mi Piace

Un rapido aggiornamento @lindsey @RGJ

Abbiamo avuto un messaggio con @all che abbiamo eliminato. Tuttavia, questo non ha risolto il problema. La query continua a tornare ogni 5 minuti e sta richiedendo un tempo infinito, al punto che c’è una coda di molte altre query.
Una volta disabilitata la chat, il carico della CPU è sceso al 15%. Pazzesco.

Devi andare nel database e rimuovere i record delle menzioni

psql: delete from chat_mentions where chat_message_id = X
dove X è l’ID del messaggio che hai rimosso.

Una query più generica è descritta nel mio messaggio qui, regola il numero come ritieni opportuno.

1 Mi Piace

Sì, ci abbiamo già provato.

Per riferimento, queste sono le nostre statistiche:

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 Mi Piace

L’unico motivo per cui quella query può richiedere molto tempo è a causa delle numerose voci nella tabella chat_mentions. Hai provato la query generica che ho postato? Forse non è @all ma un altro gruppo numeroso che viene menzionato.

La query problematica cerca tutte le menzioni dalle chat degli ultimi 7 giorni.

Dovresti anche terminare tutte le istanze esistenti della query.

Sì, li abbiamo uccisi ma continuano a tornare.
Abbiamo controllato tutte le menzioni sopra 100 e non ne avevamo nessuna. Non sono sicuro del perché altro possa succedere.
Mi sembra che ci sia un problema fondamentale con la query, ma potrei sbagliarmi.

1 Mi Piace

Questa query è probabilmente lenta anche con una piccola quantità di menzioni. Lavorerò per risolverla.

2 Mi Piace

Ottimo. Felice di continuare a supportare dal nostro caso d’uso!

2 Mi Piace

@sok777 Avrei bisogno di un po’ della tua assistenza con questo. Vorrei dare un’occhiata al piano di query che Postgres utilizza sul tuo sito. Potresti eseguirlo sul tuo database e condividere i risultati:

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 Mi Piace