Зачем нужна команда VACUUM в PostgreSQL и как она связана с MVCC?

Ответ

Команда VACUUM в PostgreSQL — это ключевой инструмент для обслуживания базы данных, работа которой тесно связана с её архитектурой MVCC (Multi-Version Concurrency Control).

В PostgreSQL при UPDATE или DELETE старые версии строк (называемые "мертвыми кортежами" или dead tuples) не удаляются физически сразу. Вместо этого они помечаются как невидимые для будущих транзакций. Это и есть суть MVCC, позволяющая разным транзакциям видеть разные "снимки" данных без блокировок на чтение.

Со временем эти мертвые кортежи накапливаются, что приводит к "раздуванию" таблиц и снижению производительности. VACUUM решает эту проблему.

Основные задачи VACUUM:

  1. Освобождение места: VACUUM находит мертвые кортежи и помечает занимаемое ими пространство как доступное для повторного использования новыми строками внутри той же таблицы. Важно: обычный VACUUM не возвращает место операционной системе.

  2. Обновление статистики: VACUUM (особенно в паре с ANALYZE) собирает статистику о распределении данных в таблицах. Эта информация используется планировщиком запросов для построения наиболее эффективных планов выполнения.

  3. Предотвращение "обертывания" ID транзакций (Transaction ID Wraparound): Это критически важная фоновая задача. VACUUM помечает старые транзакции как "замороженные", чтобы счетчик ID транзакций мог безопасно использоваться повторно, предотвращая остановку базы данных.

Виды VACUUM:

  • VACUUM: Стандартная, неблокирующая операция. Может выполняться параллельно с чтением и записью в таблицу.
  • VACUUM FULL: Полностью переписывает таблицу в новый файл без мертвых кортежей, возвращая место операционной системе. Эта операция требует эксклюзивной блокировки и может быть очень долгой и ресурсоемкой.
  • VACUUM ANALYZE: Выполняет VACUUM и ANALYZE за один проход.

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

Ответ 18+ 🔞

Давай разжую про этот ваш VACUUM, а то смотрю, народ путается, как в тёмной комнате хуй с пальцем. Ситуация, внатуре, простая, но если её не понимать, можно на ровном месте накрыться медным тазом.

Представь, твоя база — это моя кухня после застолья. Я, допустим, обновил (UPDATE) салат: старый, вонючий, выкинул в ведро. Но по правилам моего дома (это и есть MVCC, ёпта), я не могу сразу вынести это ведро на помойку. Я просто ставлю его в угол и говорю: «Это, блядь, мёртвый салат, новым гостям не показывать». А новые гости (транзакции) тем временем жрут свежий салат из тазика. И так раз за разом. Ведёр с мёртвым салатом, огрызками и пустыми бутылками (DELETE) становится всё больше. Место кончается, похавать новому некуда, искать свежий салат среди этого бардака — овердохуища времени.

Вот VACUUM — это я, злой и с похмелья, который пришёл и опустошил эти вёдра обратно в раковину. Место на кухне (в таблице) освободилось, можно новую жратву класть. НО! Я мусор на улицу не вынес. Эти пустые вёдра всё ещё в доме стоят. Это обычный VACUUM.

А теперь VACUUM FULL — это когда я, блядь, устраиваю тотальную зачистку. Выношу всё дерьмо на помойку, а потом ещё и квартиру перепланировываю, чтобы места больше стало. Серьёзная, долгая и пиздец какая блокирующая операция. Пока я это делаю, ни поесть, ни посрать — всем придётся ждать.

Зачем это всё, спросишь? Да затем, чувак!

  1. Чтобы не захлебнуться в собственном дерьме. Иначе запросы будут ползать, как улитки, потому что планировщик будет копаться в куче мусора в поисках живой строки.
  2. Чтобы статистика была адекватная. VACUUM часто идёт с ANALYZE. Это как если бы я, опустошив вёдра, ещё и пересчитал, сколько у меня осталось водки и селёдки. Чтобы потом гостям (запросам) сразу говорить, где что лежит, а не искать полдня.
  3. Самое, блядь, важное — чтобы не случился «апокалипсис ID» (Transaction ID Wraparound). Представь, у тебя счётчик транзакций — как одометр в машине. Крутится-крутится, а потом обнуляется. Если к этому моменту у тебя валяются старые, не помеченные как древние, данные, база просто ебанётся и ляжет, решив, что будущее — это прошлое. VACUUM ставит на старых данных штамп «заморожено, можно не париться», и счётчик может спокойно обнулиться. Это не шутки, это пиздец какой критичный момент.

Короче, в 99% случаев за тебя это делает Autovacuum — тихий, незаметный дворник, который подтирает сопли, пока все бухают. Но знать, как он работает, надо. А то придёт день, дворник заболеет, кухня превратится в помойку, и все начнут орать: «Что за хуйня? Почему всё так медленно?». А ты будешь сидеть и думать: «Э, сабака сука... Надо было VACUUM запустить».