Нормализация против денормализации

Нормализация против денормализации — компромисс между чистотой данных и скоростью чтения.

Нормализация убирает дублирование данных, разнося их по связанным таблицам; денормализация намеренно дублирует ради скорости чтения.

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

Нормализация — разбиение данных на таблицы так, чтобы каждый факт хранился ровно в одном месте. Если у заказа хранить имя города клиента прямо в строке заказа, а клиент переедет — придётся править все его заказы, и легко получить рассогласование. Правильно — хранить город в таблице customers, а в заказе только customer_id.

-- Нормализовано: город клиента — в одном месте, заказ ссылается по id
CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT, city TEXT);
INSERT INTO customers (name, city) VALUES ('Аня','Москва'), ('Борис','Казань');

CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, amount INTEGER);
INSERT INTO orders (customer_id, amount) VALUES (1,500), (1,300), (2,900);

-- Город берём джойном, не дублируя его в каждом заказе
SELECT o.id, c.name, c.city, o.amount
FROM orders o
JOIN customers c ON c.id = o.customer_id
ORDER BY o.id;

Вывод:

1|Аня|Москва|500
2|Аня|Москва|300
3|Борис|Казань|900

Город хранится один раз в customers. Переедет Аня — меняем одну строку, и все её заказы автоматически «видят» новый город через JOIN. Нет дублирования — нет рассогласования.

Плюсы и минусы

КритерийНормализацияДенормализация
Дублированиеминимальносознательно есть
Целостностьвысокаяриск рассогласования
Запись/обновлениепроще и безопаснеенадо обновлять копии
Чтениенужны JOINбыстрее, меньше JOIN
Объёмменьшебольше

Когда денормализуют

Денормализация — это осознанный размен. Её применяют, когда чтение критично, а JOIN-ов слишком много: в аналитических витринах, кэшах, отчётах. Например, хранят уже посчитанное orders_count в строке пользователя, чтобы не агрегировать заказы при каждом показе профиля. Цена — это поле надо аккуратно поддерживать при изменении заказов.

Правило: сначала нормализуй, денормализуй по необходимости — когда профилирование показало, что JOIN-ы стали узким местом. Преждевременная денормализация порождает баги рассогласования.

Итог

  • Нормализация хранит каждый факт один раз — целостность ценой JOIN при чтении.
  • Денормализация дублирует данные ради скорости чтения — ценой сложности обновления.
  • По умолчанию нормализуй; денормализуй точечно, когда чтение доказано стало узким местом.
Проверьте себя
1. Что делает нормализация?
AДублирует данные ради скорости
BУбирает дублирование, храня каждый факт в одном месте
CУдаляет индексы
DОбъединяет все таблицы в одну
2. Какой главный минус нормализации?
AПотеря данных
BДля чтения нужны JOIN-ы, что может быть медленнее
CНевозможность обновления
DДублирование данных
3. Когда оправдана денормализация?
AВсегда с самого начала
BКогда профилирование показало, что JOIN-ы стали узким местом чтения
CКогда мало данных
DНикогда
Поддержать проект