Bloat таблиц

Тема дорожной карты · PostgreSQL

Раздувание таблиц в PostgreSQL — накопление «мёртвых» кортежей, версий строк, оставляемых операциями UPDATE и DELETE в рамках модели MVCC PostgreSQL: они занимают дисковое пространство и замедляют последовательные сканирования, делая контроль раздувания ключевой задачей администрирования баз данных. Поскольку PostgreSQL использует хранение в кучи с только-добавлением данных и помечает старые версии строк как мёртвые вместо немедленной перезаписи, интенсивные операции записи могут привести к значительному росту таблиц и их индексов относительно их логического размера данных. Команда VACUUM возвращает пространство мёртвых кортежей для повторного использования внутри той же страницы, тогда как VACUUM FULL перезаписывает всю таблицу в новый файл и возвращает пространство операционной системе — однако она требует эксклюзивной блокировки и должна применяться осторожно в продуктивной среде. Уровень раздувания можно оценить, запросив pg_stat_user_tables на предмет n_dead_tup и сравнив с n_live_tup, или с помощью специализированных запросов оценки раздувания к pg_class и pg_statistic. Контроль раздувания таблиц посредством правильно настроенных параметров autovacuum — особенно autovacuum_vacuum_scale_factor и autovacuum_vacuum_cost_delay — необходим для стабильной настройки производительности PostgreSQL и эффективного использования хранилища.

Как это работает

Bloat таблиц — цена MVCC. UPDATE и DELETE не удаляют строки — помечают dead; VACUUM возвращает место, ANALYZE обновляет статистику планировщика, REINDEX перестраивает раздутые индексы. autovacuum работает непрерывно по дефолту, но его триггеры консервативны для больших таблиц — тюньте autovacuum_vacuum_scale_factor, autovacuum_analyze_scale_factor per-table. VACUUM FULL переписывает таблицу (лочит записи!); pg_repack делает online. Смотрите pg_stat_user_tables.n_dead_tup для bloat.

Когда применять

Тюньте autovacuum агрессивно на горячих таблицах (например autovacuum_vacuum_scale_factor = 0.01 для миллион-строчных). Мониторьте bloat через pgstattuple или pgstatindex из pg_repack. pg_repack еженедельно на самых больших таблицах. Всегда ANALYZE после большой загрузки/миграции — старая статистика даёт плохие планы. Никогда VACUUM FULL под трафиком — лочит всю таблицу.

Типичные ошибки

Ловушки Bloat таблиц: игнор autovacuum до 100GB таблицы с 50GB dead-строк; transaction wraparound — миф 200-летней давности, реальный (SELECT datname, age(datfrozenxid) FROM pg_database); неконтролируемый index bloat (запросы медленнее со временем при том же row count); VACUUM FULL в пик (CEO позвонит). Мониторьте + alerts на bloat-метрики с первого дня.

Связанные понятия

Полезные ресурсы