Почему мы пробуем Postgres вместо ClickHouse для FM-аварий
В системе Fault Management события приходят потоком: новое / подтвержденное / закрытое, часто не по порядку и с дублями. Раньше мы выстраивали сложную цепочку для приёма данных: gRPC → RabbitMQ → Обработчик → clickhouse-bulk → CH (входящие) → MV → CH (состояния)
На бумаге всё логично: clickhouse-bulk собирает мелкие INSERT’ы, а Materialized Views сами раскладывают состояние. На практике запись стала узким местом.
Что болит в текущей схеме? - Тяжёлые MV на каждый INSERT. Одна входящая строка превращается в тяжёлую обработку на стороне ClickHouse с JOIN, ORDER BY и обращению к словарям. - Умножение записи. Одно событие размножалось в несколько таблиц. - Построчный текстовый SQL. Построчная сборка текста даже с буферизацией — это дорого. - Оверхед на стороне приложения. Сериализация и HTTP-прокладки между сервисами.
В результате, узкое место — в первую очередь MV + кратная запись.
Что сделали в MVP 💡 Для MVP решили проверить простую гипотезу: «А что, если убрать всё лишнее и попробовать Postgres?» Новый поток стал прозрачным: gRPC → Конвертация → ACL (Redis) → in-memory batch → Postgres
Мы отказались от MV в пользу одной партиционированной таблицы с дедупликацией через ON CONFLICT DO NOTHING. Вставка теперь асинхронная, батчами по 1000 строк.
Цифры говорят сами за себя: 📊 Нагрузочное тестирование (ghz) выдало ~4382 RPS при p99 = 79 мс.
При этом нашли неочевидный бонус: замена MessageToDict на прямой маппер отрезала лишние 10 мс задержки.
Вывод: 📌 Для нашего сценария Postgres отлично закрывает роль «горячего пути». Сейчас будем смотреть на деградацию при росте объёмов, но первые результаты очень обнадёживают.