Тема.reset_all_highest исчерпывает всё доступное дисковое пространство

При работе с локальным контейнером, в который я импортировал данные из форума SMF2 с 20+ годами активности, я столкнулся с критической ошибкой в методе Topic.reset_all_highest.
После импорта данных в моей базе данных отображается около 60 тысяч обычных тем и примерно 400 тысяч тем типа private_message. Запросы в Topic.reset_all_highest вызывают геометрический рост количества строк, из-за чего диск переполняется (при начальном свободном пространстве в 120 ГБ).
В настоящее время я пытаюсь разбить запросы на управляемые части и выполнять их напрямую в Postgres, но это, конечно, неоптимально (к тому же я не уверен, что это вообще работает и даёт корректные результаты).
Я попытался найти, сталкивался ли кто-то ещё с подобной проблемой, но ничего не нашёл, поэтому задаюсь вопросом: не может ли это быть связано с моей собственной настройкой? Для справки: я использую последнюю версию Docker.

1 лайк

Недавно я выполнил импорт небольшого объёма данных, который, похоже, бесконечно завис на Topic.reset_all_highest, и мне пришлось прервать запрос в Postgres, чтобы продолжить работу. Раньше у меня не возникало такой проблемы, и я думал, что, возможно, мой сервер Postgres был перегружен (к нему подключено несколько сайтов).

Следующим шагом я планировал перейти на другой сервер Postgres, но пока ещё не успел этого сделать.

После того как первые два этапа моего эксперимента с «разделённым запросом» прошли успешно (X и Y для публичных тем), я попробовал третий (Z), и система зависла — то есть, согласно активности PostgreSQL, запрос был активен, а утилита top показывала, что процесс потребляет 100% ресурсов.

Тогда я снова посмотрел на SQL-запрос и нашёл проблему: оба запроса заканчиваются следующим образом

      WHERE
        topics.archetype <> 'private_message' AND
        X.topic_id = topics.id AND
        Y.topic_id = topics.id AND 
          (
          topics.highest_staff_post_number <> X.highest_post_number OR
          topics.highest_post_number <> Y.highest_post_number OR
          topics.last_posted_at <> Y.last_posted_at OR
          topics.posts_count <> Y.posts_count OR
          topics.word_count <> Z.word_count
        )

(в другом случае, разумеется, в качестве архетипа указан ‘private_message’).

Это означает, что в запросе отсутствует условие Z.topic_id = topics.id, что и вызывает экспоненциальный рост нагрузки.

Изменение условия WHERE в запросах на

      WHERE
        topics.archetype <> 'private_message' AND
        X.topic_id = topics.id AND
        Y.topic_id = topics.id AND 
        Z.topic_id = topics.id AND 
          (
          topics.highest_staff_post_number <> X.highest_post_number OR
          topics.highest_post_number <> Y.highest_post_number OR
          topics.last_posted_at <> Y.last_posted_at OR
          topics.posts_count <> Y.posts_count OR
          topics.word_count <> Z.word_count
        )

решило проблему для меня.

Стоит ли мне открыть PR?

2 лайка

Думаю, да. Если вы сможете найти коммит, который это сломал, это будет ещё более убедительно.

1 лайк

Я открыл PR по этому вопросу, хотя с некоторыми неприятными ограничениями (например, я не представляю, как протестировать это изменение).

6 лайков

Это изменение выглядит правильным, сливаю его.

(С точки зрения тестирования должно быть покрытие, и простого теста будет достаточно для проверки, нам просто нужно убедиться, что регрессии нет)

5 лайков