EMZETT.
Войти

PostgreSQL VACUUM: autovacuum и раздутые таблицы

Коротко: PostgreSQL не удаляет строки сразу, а помечает их; VACUUM очищает, освобождает место для повторного использования и поддерживает статистику актуальной, обычно автоматически через autovacuum.

Подробнее: Из-за MVCC (несколько версий строки для параллельных транзакций) UPDATE и DELETE порождают мёртвые кортежи. Они остаются, пока никакой выполняющийся доступ в них больше не нуждается. VACUUM убирает их с точки зрения повторного использования.

Подробности

Что делает VACUUM

  • Помечает место мёртвых строк как доступное для повторного использования.
  • Обновляет карту видимости (ускоряет index-only-сканирования).
  • Защищает от переполнения идентификатора транзакции (wraparound) (замораживает старые строки).
  • VACUUM FULL перезаписывает таблицу и возвращает место операционной системе, но блокирует монопольно; нужен редко (альтернатива: pg_repack).
  • ANALYZE собирает статистику для планировщика запросов.

Autovacuum

Фоновый процесс запускает VACUUM/ANALYZE, когда накопилось достаточно изменений (по умолчанию: 20 % таблицы + 50 строк). Настройки: autovacuum_vacuum_scale_factor, autovacuum_naptime, для отдельной таблицы ALTER TABLE … SET (autovacuum_vacuum_scale_factor = 0.02). Никогда не отключайте. Для больших, сильно изменяемых таблиц настраивайте агрессивнее.

Выявление раздувания (bloat)

Симптомы: таблица/индекс растёт при том же объёме данных, запросы замедляются. Проверка: pg_stat_user_tables (n_dead_tup, last_autovacuum), размер через pg_total_relation_size, расширение pgstattuple. Причины: длинные транзакции или забытые открытые соединения (мешают очистке), слишком редкий autovacuum, частые массовые обновления. Решение: держать транзакции короткими, тоньше настроить autovacuum, вручную VACUUM (VERBOSE, ANALYZE) table;.

Практика и управляемые сервисы

В Neon, Supabase, RDS autovacuum в основном работает автоматически; всё же наблюдайте за шаблонами (таблицы с множеством обновлений вроде сеансов, счётчиков, очередей: лучше вставка + удаление старых строк или партиции). Удаляйте большие объёмы пакетами. Делайте резервную копию перед VACUUM FULL. Читайте pg_stat_progress_vacuum. Соединения, застрявшие в idle in transaction, — враг любого vacuum: ограничивайте через idle_in_transaction_session_timeout.

См. также: PostgreSQL, MVCC и уровни изоляции, Индексы PostgreSQL, Пулинг соединений