Ответ вслух Senior Проектирование и нормализация обновлено

Удалить 300 млн старых строк из живой таблицы

Вопрос

В таблице events 1 млрд строк, нужно удалить всё старше года (около 300 млн), и база при этом обслуживает прод. Как это сделать?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Одним DELETE нельзя: это одна многочасовая транзакция, которая держит снимок (VACUUM всё это время ничего не чистит), пишет гигабайты WAL, вызывает лаг реплик, а при ошибке всё откатывается.

Что должно прозвучать в ответе

  • Один `DELETE` на 300 млн плох: долгая транзакция, огромный WAL, лаг реплик, мёртвые строки

  • Удалять пачками по ключу (например, по 10 тыс. id) с паузами и отдельными транзакциями

  • Следить за лагом реплик и работой autovacuum во время чистки

  • Если удалить надо больше, чем остаётся, быстрее скопировать нужное в новую таблицу и переключиться

  • На будущее: партиционирование по времени и удаление партиций целиком

Что могут спросить следом

  • Как сделать пачки так, чтобы каждая находилась по индексу?
  • Что будет с размером файла таблицы после удаления?
  • Как переключить таблицу без простоя?

Разбор

Одним DELETE нельзя: это одна многочасовая транзакция, которая держит снимок (VACUUM всё это время ничего не чистит), пишет гигабайты WAL, вызывает лаг реплик, а при ошибке всё откатывается. Удаляю пачками: DELETE FROM events WHERE id IN (SELECT id FROM events WHERE created_at < now() - interval '1 year' ORDER BY id LIMIT 10000), каждая пачка в своей транзакции, с паузой и контролем лага реплик и n_dead_tup. Пачка должна находиться по индексу, иначе каждая итерация сканирует таблицу. Место после удаления переиспользуется, но файл не уменьшится: если это важно, нужен pg_repack. Если удалить надо 70% таблицы, проще скопировать живые 30% в новую таблицу, догнать изменения и переключить переименованием. А чтобы не повторять, перевожу таблицу на партиции по месяцам: тогда старое удаляется через DETACH и DROP.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.