Таблица событий на ...
 
Уведомления
Очистить всё

Таблица событий на 600 млн строк: партиции в Postgres или увозить в ClickHouse?

5 Сообщения
4 Пользователи
4 Реакции
379 Просмотры
TimurK62
Сообщения: 31
Автор темы
Читает чужие PR бэкенд-разработчик
Присоединился: 3 года назад
[#113]

Сначала цифры. Таблица events в PostgreSQL 17, 600 млн строк, растёт на 40 млн в месяц. Сама таблица 210 ГБ, индексы ещё 140. Запросы почти всегда за последние 30 дней по одному аккаунту, p95 сейчас 380 мс, полгода назад было 90. Автовакуум по ней идёт почти без перерыва. Данные старше года нужны только для годового отчёта. Вижу два пути: партиционирование по месяцам в самом Postgres или увозить события в ClickHouse, он у нас уже стоит для аналитики. Кто делал первое на живой таблице такого размера и сколько это заняло?


4 ответа
Василий1992
Сообщения: 7
Дружит с bundler data engineer
Присоединился: 3 года назад

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


Ответ
1 ответ
Виктор1987
Присоединился: 2 года назад

Пишет в irb data engineer
Сообщения: 3

А годовой отчёт по-любому в ClickHouse соберётся быстрее, его туда стоит лить в любом случае


Ответ
kostya.sokurov
Сообщения: 73
Держит прод бэкенд-разработчик, senior
Присоединился: 4 года назад

Партиционирование на живой таблице делается без простоя, но не одним ALTER. Создаёте новую партиционированную таблицу, пишете в обе, переносите историю пачками по месяцам, потом переключаете чтение и меняете имена местами. Новые партиции создавайте заранее кроном, иначе первого числа вставки упадут. Начало примерно такое:

CREATE TABLE events_new (LIKE events INCLUDING DEFAULTS)
PARTITION BY RANGE (created_at);

CREATE TABLE events_2026_03 PARTITION OF events_new
FOR VALUES FROM ('2026-03-01') TO ('2026-04-01');

Первичный ключ придётся сделать составным, с created_at, это ограничение партиционирования. Rails с 7.1 составные ключи понимает, но все find по одному id придётся пересмотреть. Зато старые месяцы потом уходят через DETACH и DROP за секунду, а не DELETE на сутки.


Ответ
TimurK62
Сообщения: 31
Автор темы
Читает чужие PR бэкенд-разработчик
Присоединился: 3 года назад

Сделали гибрид. В Postgres партиции по месяцам, держим 13 месяцев, всё старше раз в месяц уезжает в ClickHouse и отцепляется. Перенос истории шёл 9 ночей, по месяцу-полтора за ночь, в самую тяжёлую реплика отставала на 40 секунд, не больше. Итог: p95 по аккаунту за 30 дней 38 мс вместо 380. Основная таблица теперь 75 ГБ вместо 210, автовакуум по свежей партиции укладывается в минуты. Годовой отчёт в ClickHouse строится за 4 секунды, раньше его запускали на ночь. Из неприятного: два места в коде делали find по id без даты, нашли по ошибкам на стейдже до прода.


Ответ