Нормализация против денормализации
Нормализация против денормализации — компромисс между чистотой данных и скоростью чтения.
Нормализация убирает дублирование данных, разнося их по связанным таблицам; денормализация намеренно дублирует ради скорости чтения.
Что такое нормализация
Нормализация — разбиение данных на таблицы так, чтобы каждый факт хранился ровно в одном месте. Если у заказа хранить имя города клиента прямо в строке заказа, а клиент переедет — придётся править все его заказы, и легко получить рассогласование. Правильно — хранить город в таблице 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 при чтении.
- Денормализация дублирует данные ради скорости чтения — ценой сложности обновления.
- По умолчанию нормализуй; денормализуй точечно, когда чтение доказано стало узким местом.