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

Приведи пример денормализации в БД

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

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

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

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

Контекст: нормализованная схема

Рассмотрим классический пример интернет-магазина с нормализованной структурой:

-- Таблица заказов
CREATE TABLE Orders (
    OrderId INT PRIMARY KEY,
    CustomerId INT,
    OrderDate DATETIME,
    TotalAmount DECIMAL(10, 2)
);

-- Таблица клиентов
CREATE TABLE Customers (
    CustomerId INT PRIMARY KEY,
    FirstName NVARCHAR(50),
    LastName NVARCHAR(50),
    Email NVARCHAR(100),
    City NVARCHAR(50),
    Country NVARCHAR(50)
);

-- Таблица товаров в заказе
CREATE TABLE OrderItems (
    OrderItemId INT PRIMARY KEY,
    OrderId INT,
    ProductId INT,
    Quantity INT,
    UnitPrice DECIMAL(10, 2),
    FOREIGN KEY (OrderId) REFERENCES Orders(OrderId)
);

-- Таблица продуктов
CREATE TABLE Products (
    ProductId INT PRIMARY KEY,
    ProductName NVARCHAR(100),
    CategoryId INT,
    SupplierId INT
);

В этой нормализованной схеме для получения отчёта о заказах с информацией о клиентах необходимо выполнить JOIN между несколькими таблицами:

SELECT 
    o.OrderId,
    o.OrderDate,
    o.TotalAmount,
    c.FirstName,
    c.LastName,
    c.City,
    c.Country
FROM Orders o
JOIN Customers c ON o.CustomerId = c.CustomerId;

Проблема производительности

При большом объёме данных (миллионы заказов) и частых запросах для формирования отчётов, JOIN-операции становятся ресурсоёмкими. Особенно страдают аналитические запросы, где необходимо быстро получать сводные данные.

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

Мы можем денормализовать таблицу Orders, добавив в неё часто запрашиваемые данные о клиентах:

-- Денормализованная таблица заказов
CREATE TABLE Orders_Denormalized (
    OrderId INT PRIMARY KEY,
    CustomerId INT,
    
    -- Данные из таблицы Customers
    CustomerFirstName NVARCHAR(50),
    CustomerLastName NVARCHAR(50),
    CustomerCity NVARCHAR(50),
    CustomerCountry NVARCHAR(50),
    
    -- Оригинальные поля
    OrderDate DATETIME,
    TotalAmount DECIMAL(10, 2),
    
    -- Дополнительные денормализованные поля
    YearMonth CHAR(7) -- Например, '2024-01' для группировки
);

Преимущества такой денормализации:

  • Ускорение запросов на чтение: Теперь для получения отчёта не нужен JOIN с таблицей Customers:

    SELECT 
        OrderId,
        OrderDate,
        TotalAmount,
        CustomerFirstName,
        CustomerLastName,
        CustomerCity,
        CustomerCountry
    FROM Orders_Denormalized;
    
  • Упрощение аналитических запросов: Поле YearMonth позволяет быстро группировать данные по месяцам без использования функций даты в WHERE/GROUP BY:

    SELECT 
        YearMonth,
        COUNT(*) as OrderCount,
        SUM(TotalAmount) as TotalRevenue
    FROM Orders_Denormalized
    GROUP BY YearMonth;
    
  • Снижение нагрузки на JOIN-операции: Особенно важно для систем OLAP (Online Analytical Processing).

Недостатки и риски:

  • Аномалии обновления: При изменении адреса клиента нужно обновлять все связанные записи в Orders_Denormalized:

    UPDATE Orders_Denormalized
    SET CustomerCity = 'Новый город'
    WHERE CustomerId = 123;
    
  • Увеличение размера базы данных: Данные дублируются, что увеличивает требования к хранению.

  • Сложность поддержки целостности: Требуются дополнительные механизмы (триггеры, процедуры) для поддержания консистентности данных.

Практические сценарии применения:

  1. Отчётные и аналитические системы: Data warehouses часто используют денормализованные схемы (звёздная схема, снежинка).

  2. Высоконагруженные веб-приложения: Кэширование часто запрашиваемых данных в денормализованном виде.

  3. Системы реального времени: Когда важна минимальная задержка при чтении данных.

Реализация в C# приложении:

// Денормализованная модель для DTO
public class DenormalizedOrderDto
{
    public int OrderId { get; set; }
    public DateTime OrderDate { get; set; }
    public decimal TotalAmount { get; set; }
    
    // Денормализованные поля клиента
    public string CustomerFirstName { get; set; }
    public string CustomerLastName { get; set; }
    public string CustomerCity { get; set; }
    
    // Метод для заполнения денормализованных полей
    public void DenormalizeCustomerData(Customer customer)
    {
        CustomerFirstName = customer.FirstName;
        CustomerLastName = customer.LastName;
        CustomerCity = customer.City;
    }
}

// Сервис для работы с денормализованными данными
public class OrderDenormalizationService
{
    public void UpdateDenormalizedCustomerData(int customerId, Customer updatedCustomer)
    {
        // Обновляем все заказы с данным клиентом
        var orders = _orderRepository.GetOrdersByCustomer(customerId);
        foreach (var order in orders)
        {
            order.CustomerFirstName = updatedCustomer.FirstName;
            order.CustomerLastName = updatedCustomer.LastName;
            _orderRepository.Update(order);
        }
    }
}

Вывод

Денормализация — это компромисс между производительностью чтения и сложностью поддержки целостности данных. Её следует применять осознанно, когда:

  1. Запросы на чтение значительно преобладают над запросами на запись
  2. Критически важна скорость отклика системы
  3. Данные изменяются относительно редко
  4. Существуют чётко определённые паттерны доступа к данным

В современных системах часто используют гибридный подход: нормализованная схема для операционных данных (OLTP) и денормализованная — для аналитики (OLAP) с регулярной синхронизацией через ETL-процессы.

Приведи пример денормализации в БД | PrepBro