Что такое autovacuum и как настраивать его поведение?
Autovacuum — фоновый демон, очищающий dead tuples и обновляющий статистику. Настраивается через autovacuum_vacuum_scale_factor, vacuum_cost_delay и per-table параметры ALTER TABLE ... SET (...).
Что такое autovacuum
Autovacuum — фоновый демон PostgreSQL, который автоматически запускает VACUUM и ANALYZE на таблицах. Он решает три задачи: освобождает мёртвые строки (dead tuples), созданные UPDATE/DELETE, обновляет статистику для планировщика запросов и предотвращает Transaction ID Wraparound — одну из самых критичных аварий в PostgreSQL.
Каждая строка в таблице хранит xmin/xmax — номера транзакций. Когда строка удаляется или обновляется, старая версия становится dead tuple. Без регулярной очистки таблица разрастается (table bloat), индексы замедляются, а планировщик строит неоптимальные планы из-за устаревшей статистики.
Как autovacuum принимает решение о запуске
Autovacuum запускает VACUUM для таблицы, когда количество dead tuples превышает порог:
-- Порог = autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor * reltuples
-- По умолчанию: 50 + 0.2 * размер_таблицы
-- Т.е. для таблицы в 1 000 000 строк запуск при 200 050 dead tuples
SELECT schemaname, relname,
n_dead_tup,
n_live_tup,
last_autovacuum,
last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;
Ключевые параметры и их настройка
Параметры можно задавать глобально в postgresql.conf или на уровне конкретной таблицы через ALTER TABLE ... SET (storage_parameter = value).
- autovacuum_vacuum_scale_factor — доля dead tuples от размера таблицы. По умолчанию 0.2 (20%). Для больших таблиц (10M+ строк) снижайте до 0.01–0.05, иначе vacuum будет запускаться слишком редко.
- autovacuum_vacuum_threshold — абсолютный минимум dead tuples до запуска. По умолчанию 50.
- autovacuum_analyze_scale_factor — доля изменённых строк для запуска ANALYZE. По умолчанию 0.1.
- autovacuum_vacuum_cost_delay — задержка между «порциями» работы в мс. В PG 13+ дефолт 2 мс (был 20). Уменьшение ускоряет vacuum, но увеличивает I/O нагрузку.
- autovacuum_vacuum_cost_limit — суммарный cost за один «выдох» vacuum. По умолчанию 200. На SSD можно поднять до 400–800.
- autovacuum_max_workers — максимальное число параллельных воркеров. По умолчанию 3.
-- Настройка на уровне конкретной таблицы (приоритетнее глобальных)
ALTER TABLE orders SET (
autovacuum_vacuum_scale_factor = 0.01,
autovacuum_vacuum_threshold = 1000,
autovacuum_analyze_scale_factor = 0.005,
autovacuum_vacuum_cost_delay = 2
);
-- Посмотреть текущие настройки таблицы
SELECT reloptions FROM pg_class WHERE relname = 'orders';
Мониторинг autovacuum
-- Активные воркеры прямо сейчас
SELECT pid, datname, relid::regclass, phase, heap_blks_scanned,
heap_blks_vacuumed, index_vacuum_count
FROM pg_stat_progress_vacuum;
-- Таблицы, которые давно не видели vacuum
SELECT relname,
last_autovacuum,
last_autoanalyze,
n_dead_tup,
n_mod_since_analyze
FROM pg_stat_user_tables
WHERE last_autovacuum < NOW() - INTERVAL '1 day'
OR last_autovacuum IS NULL
ORDER BY n_dead_tup DESC;
Принудительный ручной запуск
-- VACUUM без блокировки таблицы
VACUUM (VERBOSE, ANALYZE) orders;
-- VACUUM FULL — переписывает таблицу, требует ACCESS EXCLUSIVE lock
-- Использовать только в окно обслуживания!
VACUUM FULL orders;
Подводные камни
- Долгие транзакции блокируют vacuum. Autovacuum не может удалить dead tuples, если есть открытая транзакция, начатая раньше этих строк. Мониторьте
pg_stat_activityна предмет транзакций старше нескольких минут и выставляйтеstatement_timeout/idle_in_transaction_session_timeout. - Отставание autovacuum на больших таблицах. При scale_factor = 0.2 на таблице в 50M строк vacuum запустится только при 10M dead tuples. Настраивайте per-table параметры.
- autovacuum_vacuum_cost_delay слишком высокий (дефолт был 20 мс до PG 13). Vacuum «дышит» слишком медленно и не успевает за темпом записи.
- VACUUM FULL в продакшене без окна. Он берёт ACCESS EXCLUSIVE lock и блокирует все запросы. Используйте pg_repack вместо VACUUM FULL для онлайн-дефрагментации.
- Недостаточно воркеров. Если у вас сотни активных таблиц с высоким DML, трёх воркеров по умолчанию не хватает. Поднимайте
autovacuum_max_workersдо 5–8. - Игнорирование wraparound vacuum. Когда таблица достигает
autovacuum_freeze_max_age(200M транзакций), запускается агрессивный vacuum, который нельзя отменить и который не учитывает cost_delay. Это может неожиданно просадить I/O в пике. - Toast-таблицы тоже bloat'ятся. У каждой таблицы с полями text/jsonb есть скрытая TOAST-таблица. Она имеет собственные autovacuum-настройки и может разбухнуть незаметно.
Common mistakes
- Отвечать про autovacuum как про абстрактный SQL без учета MVCC, WAL, planner или конкретной версии PostgreSQL.
- Переносить поведение MySQL или ClickHouse на PostgreSQL без проверки документации.
- Не связывать механизм с последствиями для индексов, транзакций, блокировок или эксплуатации.
- Показывать синтаксис, который не поддерживается PostgreSQL.
What the interviewer is testing
- Кандидат объясняет autovacuum через реальный механизм PostgreSQL, а не общими словами.
- Приводит корректный SQL или диагностический запрос для этой СУБД.
- Называет ограничения, версионные отличия или эксплуатационные последствия.
- Связывает ответ с проектированием приложения, производительностью, надежностью или безопасностью.