Postgres a 100% de CPU pour les grandes bases de données, Discourse 2.7.7

Bonjour,

Nous exécutons Discourse 2.7.7 basé sur Docker avec une très grande base d’utilisateurs. Après la mise à niveau de la version 2.4.2 vers la 2.7.7, nous constatons que certains processus Postgres sont bloqués à 100 % d’utilisation du CPU. Une investigation plus poussée révèle que des requêtes de ce type semblent être à l’origine du problème :

discourse_prod=# select pid, datid, query from pg_stat_activity WHERE pid = '244906';
  pid   |  datid  |                         query
--------+---------+-------------------------------------------------------
 244906 | 2068583 | DELETE FROM user_badges                              +
        |         |   WHERE id IN (                                      +
        |         |     SELECT ub.id                                     +
        |         |     FROM user_badges ub                              +
        |         |     LEFT JOIN (                                      +
        |         |       SELECT id user_id, current_timestamp granted_at+
        |         | FROM users                                           +
        |         | WHERE id  IN (                                       +
        |         |        SELECT p1.user_id                             +
        |         |        FROM post_custom_fields pc                    +
        |         |        JOIN badge_posts p1 ON p1.id = pc.post_id     +
        |         |        JOIN topics t1 ON p1.topic_id = t1.id         +
        |         |        WHERE p1.user_id <> t1.user_id AND            +
        |         |                     name = 'is_accepted_answer' AND  +
        |         |             p1.user_id IN (                          +
        |         |                    SELECT user_id                    +
        |         |                    FROM posts                        +
        |         |                    WHERE TRUE OR  p1.id IN (-1)      +
        |         |             )                                        +
        |         |         GROUP BY p1.user_id                          +
        |         |         HAVING COUNT(*) > 9                          +
        |         | )                                                    +
        |         |     ) q ON q.user_id = ub.user_id                    +
        |         |                                                      +
        |         |     WHERE ub.badge_id = 103 AND q.user_id IS NULL    +
        |         |   )                                                  +
        |         |
(1 row)

Nous avons repéré cette requête qui, je suppose, va générer une surcharge énorme, n’est-ce pas ?

        |         |                    SELECT user_id                    +
        |         |                    FROM posts                        +
        |         |                    WHERE TRUE OR  p1.id IN (-1)      +

Avez-vous des suggestions à ce sujet ?
N’hésitez pas à me demander des informations supplémentaires si nécessaire.

Merci,
Daniel.

Cette requête semble provenir de Jobs::BadgeGrant.

Nous avons constaté que le problème était causé par une requête SQL personnalisée dans un badge utilisateur. Il ne s’agit donc pas d’un problème en amont. Merci.

Je soupçonne que vous voudrez également vous assurer de procéder à la commande VACUUM et de réindexer comme décrit dans Mise à jour PostgreSQL 13.