← Назад к вопросам

Что такое VACUUM в PostgreSQL?

2.0 Middle🔥 121 комментариев
#Базы данных#Производительность и оптимизация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Основное назначение VACUUM в PostgreSQL

VACUUM — это критически важная операция обслуживания, встроенная в PostgreSQL, предназначенная для двух ключевых задач: освобождения пространства, занимаемого "мёртвыми" кортежами (dead tuples), и обновления статистики для планировщика запросов. Без неё база данных со временем деградирует по производительности и расходует дисковое пространство крайне неэффективно.

Концептуально, VACUUM решает проблему, проистекающую из многопоточности и ACID-гарантий PostgreSQL. Когда вы обновляете или удаляете строку, PostgreSQL не удаляет её физически сразу (это называется MVCC — Multiversion Concurrency Control). Вместо этого старая версия строки (кортеж) помечается как "мёртвая", но остаётся в таблице до тех пор, пока не станет безопасно её удалить. Она нужна для обеспечения изоляции транзакций.

Проблемы, которые решает VACUUM

Если VACUUM не выполняется регулярно, возникают следующие проблемы:

1. Растущее потребление дискового пространства ("раздувание", bloat).

Таблица может занимать в десятки раз больше места, чем размер полезных данных, из-за накопления мёртвых кортежей.

2. Падение производительности.

  • Запросы к таблицам начинают работать медленнее, так как планировщику приходится читать с диска и мёртвые кортежи.
  • Индексы также "раздуваются" – в них остаются ссылки на несуществующие строки.
  • Замедление работы самого VACUUM – чем больше накоплено мёртвых данных, тем дольше он будет работать.

3. Риск остановки из-за "зацикливания по номерам транзакций" (wraparound).

Это самая опасная проблема. PostgreSQL использует 32-битные идентификаторы транзакций (XID). Их объём ограничен (~4 млрд). Когда старость самой старой незавершённой транзакцией приближается к этому лимиту, PostgreSQL принудительно переходит в аварийный режим и останавливает запись, чтобы предотвратить потерю данных. Только VACUUM (обычно VACUUM FREEZE) может "заморозить" старые строки, отметив их как видимые для всех будущих транзакций, и предотвратить wraparound.

Типы VACUUM

Обычный VACUUM (VACUUM, без FULL)

Это неблокирующая операция (чтение и запись таблицы возможны). Она:

  • Помечает пространство, занятое мёртвыми кортежами, как пригодное для повторного использования внутри этой же таблицы (но не возвращает его операционной системе).
  • Обновляет статистику планировщика (pg_stat_all_tables).
  • "Подрезает" концы файлов таблицы, если они полностью пусты.
-- Простейший вызов для таблицы
VACUUM анализы;
-- Для всей базы данных (рекомендуется для autovacuum)
VACUUM;

Полный VACUUM (VACUUM FULL)

Это блокирующая операция (таблица блокируется на запись, часто и на чтение). Она:

  • Полностью переписывает таблицу на диске, оставляя только "живые" строки.
  • Возвращает освобождённое пространство операционной системе.
  • Уменьшает размер индексов, эффективно перестраивая их.
  • Используется только в крайних случаях при сильном раздувании, так как требует эксклюзивной блокировки и временного двойного дискового пространства.
-- ВНИМАНИЕ: Блокирует таблицу на длительное время!
VACUUM FULL истории_болезней;

Autovacuum: Автоматическое обслуживание

Autovacuum — это фоновый демон, который автоматически запускает команду VACUUM и ANALYZE. Он является ключевым компонентом для стабильной работы PostgreSQL и включён по умолчанию. Его задача — обслуживать таблицы до того, как проблемы станут критическими.

Принцип работы:

Autovacuum отслеживает количество изменённых и удалённых строк в таблицах. Когда достигается пороговое значение (которое рассчитывается на основе параметров autovacuum_vacuum_threshold и autovacuum_vacuum_scale_factor), демон запускает VACUUM для этой таблицы.

  • Пример: Порог = 50 строк + 0,2 от размера таблицы. Для таблицы в 10 000 строк VACUUM запустится после ~2050 изменений/удалений (50 + 10000*0,2).

Параметры и мониторинг

Для fine-tuning и мониторинга используются:

  • Представления pg_stat_all_tables и pg_stat_user_tables:
    SELECT schemaname, relname, n_live_tup, n_dead_tup,
           last_vacuum, last_autovacuum
    FROM pg_stat_user_tables
    WHERE n_dead_tup > 0
    ORDER BY n_dead_tup DESC;
    
  • Представление pg_stat_progress_vacuum (PG12+) для отслеживания хода выполнения.
  • Важные параметры postgresql.conf: autovacuum, autovacuum_vacuum_scale_factor, autovacuum_vacuum_threshold, autovacuum_max_workers, autovacuum_naptime.

Практические рекомендации

  1. Никогда не отключайте autovacuum глобально. Его настройку можно корректировать для отдельных очень активных таблиц.
  2. Регулярно мониторьте n_dead_tup. Высокое и постоянно растущее значение — сигнал для анализа.
  3. VACUUM FULL — это последнее средство. Рассмотрите как альтернативу утилиту pg_repack, которая выполняет перестроение таблицы без эксклюзивной блокировки.
  4. Для очень больших таблиц часто имеет смысл уменьшить autovacuum_vacuum_scale_factor и увеличить пороговое значение, чтобы autovacuum срабатывал чаще, но обрабатывал меньше данных за раз.
  5. Транзакции, которые долго не завершаются ("долгожители"), блокируют очистку мёртвых кортежей, созданных после их начала. Это главный враг VACUUM и причина раздувания.

В итог, VACUUM — это не опция, а жизненно важный механизм "сборки мусора" PostgreSQL, который обеспечивает долгосрочную стабильность, производительность и предотвращает катастрофические сбои. Правильная настройка autovacuum — одна из ключевых обязанностей администратора.

Что такое VACUUM в PostgreSQL? | PrepBro