Что такое денормализация в базах данных?

«Что такое денормализация в базах данных?» — вопрос из категории Базы данных, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Денормализация — это сознательное отступление от нормальных форм реляционной базы данных путем введения контролируемой избыточности данных. Цель — оптимизировать скорость выполнения операций чтения за счет увеличения объема данных и усложнения операций обновления.

Типичный сценарий из моего опыта: В системе отчетов для агрегации данных требовались сложные JOIN между таблицами Orders, Customers и Products. Это замедляло генерацию ежедневных дашбордов.

До (нормализованная схема):

CREATE TABLE Orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    product_id INT,
    quantity INT,
    FOREIGN KEY (customer_id) REFERENCES Customers(customer_id),
    FOREIGN KEY (product_id) REFERENCES Products(product_id)
);
-- Для отчета нужен JOIN:
SELECT o.order_id, c.name, p.product_name, o.quantity
FROM Orders o
JOIN Customers c ON o.customer_id = c.customer_id
JOIN Products p ON o.product_id = p.product_id;

После (денормализованная схема):

CREATE TABLE Denormalized_Orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    customer_name VARCHAR(100), -- Данные из Customers
    product_id INT,
    product_name VARCHAR(100),  -- Данные из Products
    product_price DECIMAL(10,2), -- Еще данные из Products
    quantity INT,
    total_price DECIMAL(10,2) AS (product_price * quantity) -- Вычисляемое поле
);
-- Теперь отчет формируется без JOIN:
SELECT order_id, customer_name, product_name, quantity, total_price
FROM Denormalized_Orders;

Плюсы:

  • Резкое ускорение SELECT-запросов за счет исключения дорогостоящих операций JOIN.
  • Упрощение схемы БД для систем аналитики (OLAP) и чтения.

Минусы и риски:

  • Аномалии обновления: Изменение имени продукта в таблице Products потребует обновления всех связанных строк в Denormalized_Orders.
  • Увеличение занимаемого места.
  • Усложнение логики обновления: Требуются триггеры или процедуры для поддержания согласованности.

Когда это оправдано: В read-heavy системах (отчеты, аналитика, кэши), где производительность чтения критична, а данные обновляются редко (например, через ETL-процессы ночью).