PostgreSQL LinuxWindowsmacOS

Почему VACUUM не возвращает место операционной системе после DELETE

  • Обновлено
  • Чтение ≈ 5 минут

Краткий ответ

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

В этой статье
  1. Что означает ошибка
  2. Как различить причины
  3. Пошаговая диагностика и устранение
  4. Воспроизведение и проверка только в отдельной тестовой базе
  5. Как убедиться в исправлении и что делать дальше

#Что означает ошибка

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

#Как различить причины

Возможная причинаКак узнатьЧто делать
Освобождено место внутри таблицы, а не на дискеСтандартный VACUUM очищает мёртвые версии и оставляет большую часть страниц для следующих INSERT.Размер файла почти не изменился, а n_dead_tup уменьшается и новые записи помещаются без роста файла.Считать внутреннее повторное использование нормальным; отдельно оценить необходимость уменьшения файла.
Есть длительная транзакция или удерживающий горизонт репликацииСтарые снимки, replication slots или длительные запросы могут мешать очищать версии строк.pg_stat_activity показывает старую транзакцию; статистика dead tuples не уменьшается как ожидалось.Сначала выяснить владельца блокирующей транзакции и репликации, а не прерывать их.
Ожидается уменьшение таблицы/индексовПосле массового удаления в файле и индексах остаётся свободное пространство.pg_total_relation_size больше pg_relation_size; значение остаётся высоким.Вариант перепаковки возможен только в окно обслуживания после оценки диска и блокировок.

#Пошаговая диагностика и устранение

  1. Убедитесь, что удаление действительно завершилосьОткройте psql или pgAdmin → база → Tools → Query Tool. Выполните SELECT current_database(), current_user; и безопасный SELECT COUNT(*) по той таблице, где уже было удаление, если таблица не слишком велика; на огромных таблицах вместо COUNT используйте оценку pg_class. Если запрос на удаление ещё не COMMIT, не пытайтесь VACUUM для этой же операции: сначала разберитесь с транзакцией.
  2. Разделите размер таблицы и свободное место файловой системыНа Linux откройте терминал и выполните df -h, чтобы увидеть свободное место на файловой системе, содержащей кластер. На Windows откройте Проводник → «Этот компьютер» → свойства нужного диска. Сам каталог данных узнают у администратора либо через SHOW data_directory, если разрешено; не открывайте системные файлы базы вручную.
  3. Посмотрите размер таблицы до дальнейших действийВ psql запустите SELECT pg_size_pretty(pg_relation_size('public.orders'::regclass)), pg_size_pretty(pg_total_relation_size('public.orders'::regclass));, заменив public.orders реальным именем. Первое измеряет основной файл таблицы, второе — вместе с индексами и TOAST. Если таблица не существует в данной схеме, проверьте название, а не создавайте её повторно.
  4. Проверьте мёртвые строки и время последнего VACUUMВыполните запрос к pg_stat_user_tables по имени таблицы; найдите n_dead_tup, last_vacuum, last_autovacuum, n_live_tup. Это оценочные показатели, а не точная инвентаризация каждой строки. Сравните их с историей удаления и предыдущим замером: когда mёртвых строк стало меньше, обычный VACUUM, вероятно, сделал свою работу.
  5. Разрешите обычному VACUUM закончить корректноЕсли массовое удаление уже подтверждено и нет длительной транзакции, проверьте, не выполняется ли autovacuum, через pg_stat_progress_vacuum в поддерживаемой версии. На своей тестовой базе разрешено выполнить VACUUM (VERBOSE, ANALYZE) public.orders; вне BEGIN, заменив имя таблицы. На рабочей — согласуйте нагрузку с администратором. После выполнения переснимите статистику: отсутствие уменьшения файла не означает неуспех.
  6. Проверьте, не мешают ли старые снимкиАдминистратор должен изучить сессии с долгими транзакциями и репликацию, прежде чем решать о сжатии. В pg_stat_activity смотрят xact_start и backend_xmin, у репликационных слотов — xmin/catalog_xmin. Не завершайте неизвестную транзакцию и не удаляйте replication slot: это может повредить репликацию или резервное восстановление.
  7. Оцените альтернативу уменьшению файлаЕсли место нужно вернуть операционной системе, сначала выясните, будет ли таблица вновь расти: если да, сохранение свободных страниц может быть выгоднее. VACUUM FULL требует эксклюзивной блокировки таблицы, места на переписывание и времени обслуживания; иногда подходит плановая миграция/перепаковка. Не включайте его в автоматический скрипт устранения нехватки места.
  8. Сравните результат и подготовьте план откатаПовторите pg_relation_size, pg_total_relation_size и df -h, записав значения до/после; проверьте реальные INSERT/SELECT на тестовой копии. Для обычного VACUUM откат не нужен и он не должен уничтожать живые строки; результаты файловой перепаковки через ROLLBACK после завершения вернуть нельзя. Если свободного места критически мало, остановите потенциально разрушающие операции и попросите администратора расширить диск/провести обслуживание.
  9. Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
    Выберите подходящий вариант — это не команды для последовательного выполнения
    Вариант 1Замените public.orders существующей таблицей.
    SQLКоманда
    Замените public.orders существующей таблицей. Только чтение; при отсутствии объекта команда сообщает ошибку, а не создаёт объект.
    SELECT pg_size_pretty(pg_relation_size('public.orders'::regclass)) AS table_file, pg_size_pretty(pg_total_relation_size('public.orders'::regclass)) AS table_with_indexes;
    Вариант 2Замените схему и таблицу.
    SQLКоманда
    Замените схему и таблицу. Показатели приблизительные; выполняется без изменения данных.
    SELECT schemaname, relname, n_live_tup, n_dead_tup, last_vacuum, last_autovacuum FROM pg_stat_user_tables WHERE schemaname='public' AND relname='orders';
    Вариант 3Только Linux: открыть обычный терминал.
    Linux · Терминал (Bash)Только проверка
    Только Linux: открыть обычный терминал. Команда читает свободное пространство разделов, не удаляет файлов.
    df -h
    Вариант 4В psql вне блока BEGIN, в ТЕСТОВОЙ базе с настоящей таблицей вместо public.orders.
    SQLС осторожностью
    В psql вне блока BEGIN, в ТЕСТОВОЙ базе с настоящей таблицей вместо public.orders. Нагрузка на диск и изменение статистики; на рабочем сервере требуется окно обслуживания.
    VACUUM (VERBOSE, ANALYZE) public.orders;

    Команда может изменить состояние системы или её настройки. Проверьте параметры и последствия перед запуском.

#Воспроизведение и проверка только в отдельной тестовой базе

SQL
Минимальный безопасный просмотр размерности на встроенном системном каталоге, не требует создания и удаления таблиц. Возвращает два значения, но не обязан показывать уменьшение после VACUUM.
SELECT pg_size_pretty(pg_relation_size('pg_class'::regclass)) AS file_size, pg_size_pretty(pg_total_relation_size('pg_class'::regclass)) AS total_size;

#Как убедиться в исправлении и что делать дальше

При успехе VACUUM освободил версии строк для повторного использования, n_dead_tup уменьшился с учётом неточности статистики, а приложение корректно читает и записывает данные. Место на диске может остаться прежним — это нормально. Если реальная цель уменьшить файл, передайте владельцу БД измерения, доступный запас диска, допустимое окно блокировки и план резервного копирования.

Источники и обновления

Последнее обновление статьи: 2 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.