Раздувание таблиц в PostgreSQL: что проверять на ревью
После UPDATE и DELETE таблица PostgreSQL не обязательно становится меньше: старые версии строк могут занимать место, а индексы — расти отдельно. Разбираем, что проверить на ревью, как отличить проблему от нормальной работы MVCC и какие замеры собрать до изменений.

Большой размер таблицы ещё не доказывает раздувание
В PostgreSQL 16 операция UPDATE обычно создаёт новую версию строки, а DELETE помечает строку удалённой; физическое место не исчезает сразу. Если на ревью виден рост таблицы, одного графика размера недостаточно: нужно понять, сколько места занимают живые данные, сколько — версии строк, доступные для очистки, и не растут ли вместо таблицы её индексы или TOAST-хранилище.
Угол этой проверки — не поиск одной «магической» настройки, а ревью причин роста: частоты обновлений, работы autovacuum, длительных транзакций и выбора измерений. Ниже — подход для PostgreSQL 16; названия и поведение системных представлений проверяйте по документации именно вашей версии.
Сначала уточните, что именно выросло
Сравните размеры самой таблицы, её индексов и связанных данных. Функция pg_total_relation_size учитывает таблицу, индексы и TOAST; размер только основного файла не показывает полную цену хранения. Если растут индексы, разбор причин может отличаться от ситуации, когда увеличивается основная таблица.
Посмотрите на pg_stat_user_tables: число n_dead_tup — оценка мёртвых версий строк, а не точный подсчёт байтов мусора. Сопоставляйте её с общим размером отношения, числом изменений, временем последнего vacuum и динамикой за несколько интервалов. Один снимок статистики легко вводит в заблуждение: оценки обновляются не непрерывно и сами по себе не объясняют, сколько места можно вернуть.
Раздувание — не отдельный счётчик в PostgreSQL, а ситуация, когда физическое место заметно превышает нужное для текущих данных и нормального запаса под обновления. Свободное место внутри файла не всегда бесполезно: его можно повторно использовать при записи новых версий строк.
Что проверять в изменениях и настройках
| Что ревьюить | На что смотреть | Почему это важно |
|---|---|---|
| Профиль записи | Частые UPDATE, массовые удаления, обновление тех же строк | Создаются новые версии строк, а старые становятся кандидатами на очистку |
| Autovacuum | Последний запуск, накопление мёртвых строк, настройки таблицы и базы | Общие настройки могут не подходить большой или активно изменяемой таблице |
| Долгие транзакции | Открытые транзакции и старые снимки в активности базы | Они могут мешать удалять версии строк, которые ещё потенциально видимы |
| Индексы и TOAST | Отдельную динамику их размеров и характер обновляемых столбцов | Общий размер отношения растёт не только из-за основной таблицы |
| Метод измерения | Оценки статистики против прямого подсчёта и замеров во времени | Нельзя обосновать дорогую операцию одним приблизительным числом |
1. Не перепутайте частые обновления с ошибкой autovacuum
В ревью ищите, какие столбцы меняются и как часто. Если приложение обновляет запись даже тогда, когда значение не изменилось, оно может создавать лишнюю работу для таблицы. Особенно внимательно проверяйте массовые задания, синхронизацию и обработчики, которые многократно перезаписывают одни и те же строки.
У UPDATE есть шанс пройти как HOT-обновление: PostgreSQL может не создавать новые записи во всех индексах, если обновляемые столбцы не затрагивают индексируемые значения и на странице хватает места. Поэтому ревьюируйте и набор индексов, и запас свободного места на страницах. Удаление нужного индекса ради уменьшения роста — не универсальный ответ: сначала оцените его роль в запросах.
2. Проверьте, успевает ли autovacuum за таблицей
Для autovacuum важен не только общий флаг включения. В PostgreSQL 16 порог запуска vacuum для таблицы рассчитывается с учётом базового порога и доли от числа строк; на поведение также влияют настройки таблицы и базы. Поэтому на огромной таблице стандартная доля может означать, что накопится много изменений до запуска очистки. Но механически уменьшать параметры без оценки нагрузки тоже опасно: чаще запускающиеся процессы потребляют ресурсы и конкурируют за ввод-вывод.
Сверьте время последнего autovacuum с интервалами роста и характером записи. Если он запускается, но не успевает обработать поток изменений, ищите не только порог запуска, но и длительность работы, нагрузку на диск и ограничения видимости старых версий. В замечании на ревью просите показать конкретные настройки для таблицы и динамику статистики, а не ограничиваться фразой «autovacuum включён».
3. Найдите транзакции, удерживающие старые версии
VACUUM может очистить строку не тогда, когда её удалили, а когда старый снимок больше не может её видеть. Долгая транзакция, забытая сессия или другие механизмы удержания горизонта видимости способны задержать эту очистку. Проверьте в pg_stat_activity длительность транзакций и доступную информацию о снимках; если используется логическая репликация, отдельно изучите слоты в pg_replication_slots и значения xmin, когда они заданы.
Важно не сводить диагноз к поиску одной долгой сессии. Разбирайте, кто её открыл, почему не завершает и можно ли безопасно изменить поведение приложения. Принудительное завершение соединения может прервать рабочую транзакцию — сначала оцените последствия для сервиса.
4. Не принимайте оценку за точный объём
Для первичного наблюдения используйте статистические представления и снимайте показатели регулярно в одинаковых условиях. Если нужна оценка содержимого отношения, расширение pgstattuple предоставляет более подробную информацию; его приблизительный вариант помогает не читать подряд все страницы. Но диагностический замер тоже имеет цену: прежде чем запускать его на крупной таблице в проде, оцените ожидаемый ввод-вывод и выберите подходящее окно.
В хорошем ревью указано, что измеряли, когда, на какой базе и каким способом. Нет универсального процента «нормального раздувания» для любой таблицы: объём строк, резерв места для обновлений, индексы и профиль записи различаются. Не обещайте освобождение диска, пока не установлено, где именно находится свободное пространство и какой способ обслуживания рассматривается.
«Размер файла — симптом, а не диагноз: сначала выясните, кто удерживает место и можно ли его повторно использовать».
Какие замечания оставлять в ревью
Общие формулировки вроде «добавьте vacuum» не помогают команде проверить гипотезу. Лучше связать наблюдаемое поведение с запросом данных или конкретной настройкой:
- «Этот обработчик обновляет строку даже при неизменившемся значении. Проверьте, можно ли пропускать такие записи, и покажите влияние на число обновлений».
- «Таблица растёт быстрее, чем очищается. Добавьте замеры n_dead_tup, времени последнего autovacuum и общего размера отношения за одинаковые интервалы».
- «Настройка autovacuum для этой таблицы отличается от общей. Обоснуйте пороги ожидаемым числом обновлений и нагрузкой, а не только текущим размером файла».
- «Предложение выполнить VACUUM FULL не описывает блокировку и запас свободного диска. Укажите окно обслуживания, ожидаемую длительность и план отката».
- «Общий размер вырос, но размер индексов отдельно не проверен. Разделите измерения таблицы, индексов и TOAST до вывода о причине».
Где подход ломается
Во-первых, статистику легко прочитать как точную телеметрию, хотя это оценки и агрегированные данные. Во-вторых, разовое сокращение dead tuples не обязательно уменьшит файл на диске: VACUUM обычно делает место повторно доступным для самой таблицы, а не возвращает его операционной системе. В-третьих, VACUUM FULL — не «обычный vacuum побыстрее»: он переписывает таблицу, требует блокировки, мешающей обычному доступу, и дополнительного дискового пространства.
Отдельная ловушка — менять fillfactor, пороги autovacuum или набор индексов без контрольного замера. Для каждого изменения зафиксируйте исходные размеры и статистику, нагрузку записи и план проверки после выкладки. Сравнение имеет смысл только при сопоставимом трафике и объёме данных.
Что делать дальше
Начните с таблиц, которые растут быстрее остальных: снимите размеры таблицы, индексов и TOAST, статистику мёртвых строк и время последнего autovacuum. Затем проверьте частые UPDATE, незавершённые транзакции и слоты репликации. Только после этого выбирайте настройку или операцию обслуживания и наблюдайте, изменились ли темп роста, длительность vacuum и доступное место на диске.
Примечание: MVCC — механизм многоверсионности PostgreSQL, при котором параллельные транзакции работают с версиями строк, видимыми в их снимках. Разбор инвалидации кэшей приложений и планирования индексов выходит за рамки этой проверки.
Проектная работа: От проблемы до защиты: продукт, этапы, вопросы комиссии
Спросить за 15 ₽Источники: PostgreSQL 16: Routine Vacuuming, PostgreSQL 16: Monitoring Database Activity
Частые вопросы
Как понять, что таблица действительно раздулась?
Почему VACUUM не уменьшил файл таблицы?
Может ли одна долгая транзакция мешать очистке?
Нужно ли уменьшать порог autovacuum для большой таблицы?
Что проверять, если вырос общий размер, но сама таблица почти не меняется?
Какой показатель поставить на дашборд?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.