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

Что такое денормализация БД?

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

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

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

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

Что такое денормализация БД

Денормализация — это процесс намеренного нарушения нормальных форм базы данных путём добавления избыточных (дублируемых) данных для повышения производительности чтения данных. Денормализация — это компромисс между нормализацией и производительностью.

Нормализация vs Денормализация

Нормализация стремится:

  • Избежать дублирования данных (экономия памяти)
  • Упростить обновления (изменяем данные в одном месте)
  • Гарантировать целостность данных

Денормализация приносит:

  • Дублирование данных (больше памяти)
  • Более быстрое чтение (меньше JOIN запросов)
  • Сложность обновлений (меняем в нескольких местах)

Пример: Нормализованная структура

// Нормализованная схема БД
// Таблица users:
// id | name       | email
// 1  | John Doe   | john@example.com
// 2  | Jane Smith | jane@example.com

// Таблица orders:
// id | user_id | product    | price
// 1  | 1       | Laptop     | 1000
// 2  | 1       | Mouse      | 20
// 3  | 2       | Keyboard   | 80

public class NormalizedDB {
    public static void main(String[] args) {
        // Получение информации о заказе пользователя требует JOIN
        String sql = "SELECT u.name, o.product, o.price " +
                    "FROM users u " +
                    "JOIN orders o ON u.id = o.user_id " +
                    "WHERE u.id = 1";
        // Результат:
        // John Doe | Laptop | 1000
        // John Doe | Mouse  | 20
    }
}

Денормализованная структура

// Денормализованная схема БД
// Таблица user_orders (содержит дублированные данные):
// id | user_id | user_name  | email              | product | price
// 1  | 1       | John Doe   | john@example.com   | Laptop  | 1000
// 2  | 1       | John Doe   | john@example.com   | Mouse   | 20
// 3  | 2       | Jane Smith | jane@example.com   | Keyboard| 80

public class DenormalizedDB {
    public static void main(String[] args) {
        // Простой и быстрый запрос - нет JOIN!
        String sql = "SELECT user_name, product, price " +
                    "FROM user_orders " +
                    "WHERE user_id = 1";
        // Результат сразу!
        // John Doe | Laptop | 1000
        // John Doe | Mouse  | 20
    }
}

Стратегии денормализации

1. Дублирование часто запрашиваемых данных

// Таблица orders с дублированными данными
// order_id | user_id | user_name | user_email | product | price

public class DuplicateFrequentData {
    public static void main(String[] args) {
        // Вместо JOIN, получаем всё из одной таблицы
        String sql = "SELECT user_name, user_email, product " +
                    "FROM orders WHERE order_id = 123";
        // Один запрос вместо двух
    }
}

2. Вычисляемые столбцы

// Таблица users с денормализованным итогом
// user_id | name | total_orders | total_spent
// 1       | John | 2            | 1020
// 2       | Jane | 1            | 80

public class MaterializedColumns {
    public static void main(String[] args) {
        String sql = "SELECT name, total_orders, total_spent " +
                    "FROM users WHERE user_id = 1";
    }
}

3. Кэширование

import redis.clients.jedis.Jedis;

public class DenormalizationWithCache {
    private Jedis redis = new Jedis("localhost", 6379);
    
    public void updateUserOrder(int userId, String productName, double price) {
        // 1. Обновляем основную таблицу
        updateDB("INSERT INTO orders ...");
        
        // 2. Обновляем денормализованную таблицу
        updateDB("UPDATE user_orders SET ... WHERE user_id = " + userId);
        
        // 3. Инвалидируем кэш
        redis.del("user:" + userId + ":orders");
    }
}

Проблемы денормализации

1. Сложность обновлений

Когда обновляем имя пользователя, нужно обновить везде:

public class UpdateComplexity {
    public void updateUserName(int userId, String newName) {
        // Обновление 1: таблица users
        updateDB("UPDATE users SET name = ? WHERE id = ?", newName, userId);
        
        // Обновление 2: таблица orders (дублированные данные)
        updateDB("UPDATE orders SET user_name = ? WHERE user_id = ?", newName, userId);
        
        // Обновление 3: таблица user_orders
        updateDB("UPDATE user_orders SET user_name = ? WHERE user_id = ?", newName, userId);
        
        // Обновление 4: кэш
        redis.del("user:" + userId);
        
        // Риск несогласованности данных!
    }
}

2. Несогласованность данных

Если пропустили одно место для обновления:

user_orders: name = John Doe
user_cache: name = John Smith
users: name = John Smith
// Разные значения в разных местах!

3. Больше памяти

Денормализованная база займёт 50-100% больше места.

Когда использовать денормализацию

Используй денормализацию когда:

  • Много читающих операций, мало пишущих
  • Запросы медленны из-за множественных JOIN
  • Денормализованные данные редко меняются
  • Требуется кэширование результатов

Избегай денормализацию когда:

  • Много операций обновления
  • Данные часто изменяются
  • Важна целостность и консистентность
  • Легко оптимизировать индексами

Правильный подход

public class BestPractices {
    // 1. Начни с нормализованной схемы
    // 2. Профилируй запросы
    // 3. Если некоторые JOIN медленны, денормализуй
    // 4. Используй правильные индексы
    // 5. Рассмотри кэширование (Redis)
    // 6. Последняя опция: денормализация
    
    // Правильная последовательность оптимизации:
    // Индексы -> Кэширование -> Денормализация
}

Денормализация — мощный инструмент для оптимизации производительности, но требует осторожности в управлении целостностью данных.

Что такое денормализация БД? | PrepBro