Раздувание таблиц (bloat) - неизбежная плата за механизм MVCC (Multiversion Concurrency Control) в PostgreSQL. Когда autovacuum не справляется, а обычный VACUUM не способен вернуть место операционной системе, перед администратором встаёт выбор: запланировать жёсткую блокировку с VACUUM FULL или провести онлайн-реорганизацию через pg_repack. Разберёмся, в каких случаях оправдан каждый из инструментов и на что обратить внимание в продакшен-среде.
Почему раздувание таблиц - это проблема
Как MVCC порождает мёртвые строки
PostgreSQL обеспечивает конкурентный доступ к данным за счёт многоверсионности (MVCC). Каждое обновление или удаление не перезаписывает строку на месте, а создаёт новую версию и оставляет старую помеченной как неактуальную. Со временем доля таких «мёртвых» кортежей (dead tuples) растёт, таблица раздувается, а индексы хранят ссылки на уже невидимые данные.
Типичные сценарии: массовые UPDATE/DELETE и их последствия
Самое заметное распухание возникает после массовых операций: пакетной очистки устаревших записей, длительных миграций или сбоев в настройках autovacuum. Таблица может занимать в несколько раз больше места, чем реальный объём «живых» данных. Обычный VACUUM освобождает пространство внутри файлов таблицы, но не умеет возвращать лишние страницы файловой системе. Поэтому страдает и производительность - sequential scan вынужден обходить огромное количество пустых или мёртвых блоков.
VACUUM FULL - встроенное, но блокирующее решение
Как работает VACUUM FULL: перезапись таблицы в новый heap‑файл
VACUUM FULL действует радикально: он полностью переписывает таблицу. Создаётся новый компактный набор файлов данных, в него копируются только живые строки, после чего старый heap‑файл удаляется, а все индексы перестраиваются с нуля. Благодаря этому достигается максимальное уплотнение и операционная система гарантированно получает высвобожденное место.
Блокировки и недоступность: ACCESS EXCLUSIVE на всё время операции
Главный недостаток встроенного метода - эксклюзивная блокировка (ACCESS EXCLUSIVE), которая накладывается на целевую таблицу с первой и до последней секунды выполнения команды. На это время любые попытки читать или писать в таблицу приостанавливаются, а параллельные запросы выстраиваются в очередь. Для небольших таблиц блокировка длится секунды, но для крупных продуктивных таблиц простой может растянуться на десятки минут и часов.
Ресурсы: потребность в двойном объёме дискового пространства
Поскольку операция создаёт полную новую копию таблицы и всех её индексов, до завершения команды в файловой системе должно быть достаточно места для одновременного хранения и старого, и нового набора файлов. Это означает, что для таблицы, реально занимающей 100 ГБ дискового пространства, понадобится ещё около 100 ГБ свободного места, иначе операция не выполнится.
Когда выбирать VACUUM FULL: запланированное окно, отсутствие pg_repack, экстренное освобождение места
VACUUM FULL оправдан, если у вас есть согласованное окно обслуживания и кратковременная недоступность сервиса допустима. Его также применяют в экстренных ситуациях, когда диск заполнен настолько, что нет возможности установить расширения, или таблица не удовлетворяет требованиям pg_repack. В управляемых средах, где pg_repack не настроен или запрещён политиками безопасности, встроенная команда может оказаться единственным доступным способом гарантированно вернуть место.
pg_repack - онлайн-реорганизация без длительного простоя
Как работает pg_repack: копия, отслеживание изменений и короткое переключение
pg_repack - расширение PostgreSQL для реорганизации таблиц и индексов. Сначала оно создаёт новую, компактную версию объекта, параллельно отслеживая все изменения, которые производятся приложением в оригинальной таблице. Когда основная копия готова, pg_repack применяет накопленную дельту и на очень короткое время захватывает эксклюзивную блокировку, чтобы подменить старые файлы новыми. После этого работа приложения продолжается уже с оптимизированным хранилищем.
Блокировки: кратковременный исключительный lock только в начале и в конце
В отличие от VACUUM FULL, pg_repack удерживает ACCESS EXCLUSIVE лишь на несколько миллисекунд в начале сессии (для синхронизации метаданных) и в момент финального переключения. Всё остальное время таблица полностью доступна для чтения и записи. Поэтому сервис остаётся работоспособным даже при реорганизации очень больших производственных таблиц.
Ограничения: обязательный PRIMARY KEY или UNIQUE индекс
Ключевое ограничение pg_repack - он работает только с таблицами, у которых есть первичный ключ или хотя бы один уникальный индекс. Без надёжного способа однозначно идентифицировать каждую строку механизм отслеживания изменений не может корректно синхронизировать оригинал и копию. Если таблица не удовлетворяет этому условию, pg_repack использовать не получится.
Когда выбирать pg_repack: продакшен с критичной доступностью, облачные сервисы
Основная область применения - базы данных с высокими требованиями к непрерывности. Когда сервис должен принимать запросы круглосуточно и каждая минута простоя обходится дорого, pg_repack становится предпочтительным решением. Он же отлично подходит для управляемых облачных инсталляций вроде Amazon RDS или Aurora, где его можно подключить и использовать, соблюдая рекомендации по настройке расширений.
Сравнение VACUUM FULL и pg_repack: ключевые различия
Влияние на доступность и время блокировки
VACUUM FULL блокирует таблицу на всё время перестроения - от старта до полного завершения. pg_repack ограничивает блокировку короткими техническими интервалами. На практике это означает, что с VACUUM FULL вам придётся останавливать прикладной трафик, а с pg_repack - можно продолжать работу, не планируя полноценное окно недоступности.
Требования к свободному месту и производительность
Оба инструмента нуждаются примерно в двойном объёме дискового пространства на время операции, так как и там, и там создаётся полная копия данных с индексами. По скорости непосредственно перестроения pg_repack сопоставим с командой CLUSTER, а VACUUM FULL в зависимости от версии PostgreSQL может работать быстрее или медленнее, но не на порядки. Основной выигрыш - не в часах выполнения, а в сохранении доступа к таблице.
Зависимость от наличия первичного ключа или уникального индекса
VACUUM FULL не предъявляет никаких требований к структуре таблицы, кроме наличия достаточного места и прав. pg_repack же невозможно запустить на таблице, где отсутствуют PRIMARY KEY или UNIQUE-индексы на любом столбце или наборе столбцов. Если архитектура приложения этого не предусматривает, выбор инструмента предопределён.
Использование в управляемых сервисах (RDS, Aurora)
pg_repack доступен в Amazon RDS и Aurora, но требует осознанной настройки: добавления расширения и корректировки параметров, разрешающих его работу. VACUUM FULL работает в облаке «из коробки», но и последствия у него те же - полная блокировка. Поэтому в облаке компромисс такой же, как и на собственных серверах: хотите избежать простоя - внедряйте pg_repack.
Рекомендации по выбору инструмента
Если простой допустим
При наличии регламентного окна обслуживания, когда пользователей можно предупредить, а мониторинг приглушить, VACUUM FULL - простое и надёжное средство без дополнительных зависимостей. Оно гарантированно возвращает место и не требует установки сторонних расширений.
Если сервис должен оставаться доступным
Выбирайте pg_repack. Он даёт почти нулевое время недоступности, позволяя проводить реорганизацию в фоновом режиме без отключения прикладных систем. Перед запуском убедитесь в наличии свободного места на диске и корректно настроенном мониторинге, чтобы вовремя заметить проблемы с отслеживанием изменений.
Если на таблице нет подходящего индекса
Единственный разумный выход в такой ситуации - VACUUM FULL, либо предварительное добавление уникального индекса, если бизнес-логика это позволяет. Осознанно создавать индекс только ради запуска pg_repack стоит далеко не всегда: оцените, не дешевле ли будет запланировать короткий простой для VACUUM FULL.
Если работаете в облаке: что нужно знать о pg_repack в RDS и Aurora
Убедитесь, что в вашем облачном окружении расширение можно активировать. В RDS и Aurora потребуется добавить pg_repack в shared_preload_libraries и установить его, после чего получить кратковременную блокировку в начале работы утилиты не будет проблемой. Обязательно протестируйте процесс на копии продукционной базы - в облаке управление ресурсами может отличаться от собственного «железа».
FAQ
Можно ли использовать pg_repack, если на таблице нет первичного ключа?
Нет. Обязательное условие - наличие первичного ключа или хотя бы одного уникального индекса. Без этого pg_repack не сможет корректно отслеживать изменения строк во время перестроения.
Как понять, что пора применять VACUUM FULL или pg_repack?
Явный признак - таблица занимает заметно больше места, чем ожидается исходя из количества живых строк, при этом обычный VACUUM и повторяющийся autovacuum не возвращают дисковое пространство операционной системе. Определить уровень раздувания можно по соотношению «мёртвых» и живых кортежей в статистике, не дожидаясь заполнения диска.
Что произойдёт, если прервать pg_repack?
Процесс прекратится, временная копия таблицы будет удалена, а оригинальная таблица останется нетронутой. Никаких необратимых изменений не случится, но реорганизацию придётся запустить повторно.
Есть ли альтернативы pg_repack и VACUUM FULL?
Помимо ручного пересоздания таблицы через CREATE TABLE AS… или утилит вроде pg_squeeze, принципиальных замен с минимальным простоем немного. Выбор обычно сводится к тому, насколько критична блокировка и есть ли на таблице подходящий индекс.
Как pg_repack себя ведёт с секционированными таблицами?
pg_repack поддерживает секционированные таблицы, но в продакшен-среде часто безопаснее обрабатывать каждую секцию по отдельности. Это даёт более предсказуемое время выполнения и снижает риск блокировок на родительской структуре.
Нужно ли останавливать приложение при VACUUM FULL?
Да. Поскольку команда удерживает ACCESS EXCLUSIVE, приложение не сможет ни читать, ни писать в таблицу до завершения операции. Любой открытый или новый запрос будет ожидать снятия блокировки, что внешне эквивалентно простою сервиса для этой таблицы.
Вывод
VACUUM FULL - встроенная и радикальная мера для гарантированного возврата дискового пространства, но ценой полной недоступности данных. pg_repack сохраняет работоспособность приложений ценой дополнительных требований к структуре таблицы и настройке окружения. Универсального ответа нет: ориентируйтесь на критичность простоя, наличие первичного ключа и возможности инфраструктуры. В любом случае перед запуском протестируйте операцию на нерабочей копии и убедитесь, что свежая резервная копия под рукой.
Источники
- Removing bloat with pg_repack - AWS Prescriptive Guidance
- PostgreSQL: pg_repack vs VACUUM FULL — как лечить bloat без простоев
- PostgreSQL pg_repack vs VACUUM FULL: Choosing the Right Tool for Database Maintenance
- PostgreSQL Table Maintenance: A Comprehensive Guide to VACUUM, VACUUM FULL, and pg_repack
- How to run pg_repack on Amazon RDS and Aurora



.svg.webp)





