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.