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, Пулінг з’єднань