Ответ
В PostgreSQL удаление строк реализовано в рамках архитектуры MVCC (Multi-Version Concurrency Control), поэтому строки не удаляются физически сразу после выполнения команды DELETE
.
Процесс удаления:
- Пометка строки: Вместо физического удаления,
DELETE
помечает строку как "мертвую" (dead tuple). Это делается путем записи ID транзакции, которая выполнила удаление, в системное поле строкиxmax
. - Сохранение видимости: Старая версия строки остается видимой для транзакций, которые начались до момента фиксации удаления. Это обеспечивает изоляцию транзакций без блокировок на чтение.
- Очистка: Физическое удаление "мертвых" строк и освобождение места на диске происходит позже, во время процесса
VACUUM
.
Способы очистки:
VACUUM
: Стандартная команда, которая находит "мертвые" строки и делает занимаемое ими место доступным для новых записей. Не блокирует таблицу для чтения и записи.AUTOVACUUM
: Фоновый процесс, который автоматически выполняетVACUUM
для таблиц при достижении определенного порога измененных или удаленных строк.VACUUM FULL
: Перезаписывает всю таблицу в новый файл на диске, удаляя все "мертвые" строки и пустое пространство. Требует эксклюзивной блокировки таблицы на все время своей работы.TRUNCATE TABLE
: Быстро удаляет все строки из таблицы, не сканируя ее. Это DDL-операция, она немедленно освобождает место, но ее нельзя отменить, и она не запускает триггерыON DELETE
.
-- Помечает строку как удаленную, но место не освобождает
DELETE FROM users WHERE id = 42;
-- Физически очищает место от ранее удаленных строк
VACUUM users;
-- Быстро удаляет все строки и освобождает место
TRUNCATE TABLE users RESTART IDENTITY;