intermediate
Normalization
Снижайте duplication и update anomalies через decomposition around functional dependencies and ownership.
Нормализация декомпозирует таблицы, чтобы убрать избыточность и аномалии обновления. Каждая нормальная форма добавляет правила о функциональных зависимостях — какие неключевые атрибуты от чего зависят.
| Форма | Правило (упрощённо) | |-------|---------------------| | 1NF | Атомарные значения; без повторяющихся групп | | 2NF | Нет частичной зависимости от части составного PK | | 3NF | Нет транзитивной зависимости: неключ → неключ | | BCNF | Каждый детерминант — candidate key |
Пример аномалии без нормализации: `customer_email` на каждой строке `order_items` — смена email требует массового update; частичные обновления дают несогласованные копии.
-- До: orders(customer_email, ...) дублирует факты пользователя
-- После: orders(user_id) REFERENCES users(email)
Декомпозируйте по ownership: факты о пользователе — в `users`; о позиции заказа — в `order_items`. Join при чтении, пока замеренный горячий путь не оправдает дублирование (см. денормализацию).
На интервью: по денормализованной «табличке» найдите аномалию (insert/update/delete) и предложите таблицы в 3NF.
Типовые ошибки: чрезмерная нормализация на десятки мелких таблиц для простого CRUD; разделение сущностей, которые всегда грузятся вместе, без замера стоимости join; нормализация append-only логов, которые не обновляются.
Компромисс — между безопасностью обновлений и единым источником правды с одной стороны и сложностью join при чтении с другой: нормализуйте, пока аномалии болят, а не пока ER-диаграмма не выглядит академично.
Чеклист:
- Назовите избыточность или аномалию, которую убираете.
- Определите функциональные зависимости и ownership.
- Цель — 3NF/BCNF, если замеренный read path не говорит иначе.
- Сохраните candidate keys и FK после разбиения.
- Объясните, какие запросы получают join, а какие — более безопасные update.