← Назад к вопросам

Что такое VACUUM?

2.3 Middle🔥 81 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

VACUUM в PostgreSQL

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

Почему VACUUM необходим

В PostgreSQL используется MVCC (Multi-Version Concurrency Control) — механизм, позволяющий разным транзакциям видеть разные версии данных одновременно. Когда вы удаляете или обновляете строку, старая версия не исчезает сразу — она помечается как "мертвая", но занимает место на диске.

// Пример из приложения на Java с JDBC
public void updateUserEmail(int userId, String newEmail) {
    String sql = "UPDATE users SET email = ? WHERE id = ?";
    try (PreparedStatement stmt = connection.prepareStatement(sql)) {
        stmt.setString(1, newEmail);
        stmt.setInt(2, userId);
        stmt.executeUpdate();
        // старая версия строки помечена как "мертвая", VACUUM удалит её позже
    }
}

Два режима VACUUM

1. VACUUM (обычный)

Удаляет мертвые версии, но не блокирует таблицу (позволяет читать данные):

VACUUM users;

Внутри обновляет индексы и пространство:

  • Отмечает мертвые версии как свободные
  • Перестраивает индексы
  • Обновляет статистику

2. VACUUM FULL

Блокирует таблицу полностью, перестраивает её с нуля, освобождая максимум места:

VACUUM FULL users;

Используется редко, так как:

  • Таблица заблокирована для записи и чтения
  • Медленнее обычного VACUUM
  • Нужно только при критическом раздутии таблицы

ANALYZE — сбор статистики

Обычно используется вместе с VACUUM:

VACUUM ANALYZE users;

ANALYZE собирает статистику о распределении данных для оптимизатора:

  • Сколько строк в таблице
  • Распределение значений в колонках
  • Кардинальность индексов

План запроса строится на основе этой статистики.

Автоматический AUTOVACUUM

PostgreSQL имеет autovacuum daemon, который автоматически запускает VACUUM:

-- Проверить параметры autovacuum
SHOW autovacuum;
SHOW autovacuum_vacuum_threshold;
SHOW autovacuum_vacuum_scale_factor;

Autovacuum запускается, когда:

  • Количество мертвых строк превышает autovacuum_vacuum_threshold
  • Или: dead_tuples > threshold + table_size * scale_factor

Проблемы без регулярного VACUUM

1. Раздутие таблицы (Table Bloat)

Таблица растет бесконтрольно, занимая место на диске:

-- Проверить размер таблицы
SELECT pg_size_pretty(pg_total_relation_size(users));

2. Плохая производительность запросов

Постгрес сканирует мертвые версии, замедляя seq scan:

// Этот запрос может быть медленным без VACUUM
public List<User> getAllUsers() {
    String sql = "SELECT * FROM users WHERE status = ?";
    // PostgreSQL сканирует все версии строк, включая мертвые
}

3. XID Wraparound

При достижении максимума (232 транзакций) база может отключиться:

SELECT age(datfrozenxid) FROM pg_database WHERE datname = production;

Практические рекомендации

-- Включить/отключить autovacuum для таблицы
ALTER TABLE users SET (autovacuum_enabled = true);

-- Агрессивнее очищать таблицу
ALTER TABLE users SET (autovacuum_vacuum_scale_factor = 0.01);

-- Запустить VACUUM с дополнительной информацией
VACUUM VERBOSE ANALYZE users;

Связь с Java приложением

Для Java разработчика важно понимать:

  • Connection pooling: долгоживущие соединения могут держать транзакцию, препятствуя VACUUM
  • Long transactions: используй connection.setAutoCommit(true) для JDBC, чтобы избежать долгих транзакций
  • Batch operations: большие batch-операции требуют частого VACUUM после
// Неправильно: долгая транзакция блокирует VACUUM
try (Connection conn = dataSource.getConnection()) {
    conn.setAutoCommit(false);
    for (int i = 0; i < 1000000; i++) {
        // долгая операция
    }
    conn.commit();
}

// Правильно: батчи с коммитами
for (int i = 0; i < 1000000; i += 1000) {
    batchInsert(i, i + 1000);
    connection.commit(); // коротко
}

Вывод: VACUUM — это не просто техническая деталь. Правильно настроенный VACUUM критичен для масштабируемости и надежности PostgreSQL в production.