SQLLab
Теория· 10 мин· 15 XP

Цена хаоса: когда плохая схема убивает бизнес

Прежде чем учить нормальные формы — поймём, зачем это нужно в реальной жизни.


Кейс: интернет-магазин «МегаМаркет»

Представьте: небольшой интернет-магазин ведёт все заказы в одной таблице orders_flat:

order_idcustomer_emailcustomer_cityproductqtydiscountstore
1001ivan@mail.ruМоскваiPhone 15110%МегаЦентр
1001ivan@mail.ruМоскваAirPods210%МегаЦентр
1002ivan@mail.ruПитерMacBook15%МегаСевер

На первый взгляд всё работает. Но через год:


Инцидент 1: Двойная скидка (потери — 2 млн ₽)

Маркетолог обновляет скидку для заказа 1001:

sql
UPDATE orders_flat SET discount = '15%' WHERE order_id = 1001;

Обновилась только первая строка. Вторая строка того же заказа — iPhone и AirPods — имеют разные скидки. Система начисляет скидку дважды и неправильно. Клиенты получают неверные чеки. Финансовый отдел обнаруживает это через три месяца.

Причина: один заказ — несколько строк. Обновление частичное.


Инцидент 2: Потеря клиента (данные удалены безвозвратно)

Клиент просит удалить все свои заказы (GDPR):

sql
DELETE FROM orders_flat WHERE customer_email = 'ivan@mail.ru';

Удалены все строки. Вместе с ними — история продаж, которая нужна бухгалтерии. И адрес доставки, который нужен логистике для закрытия спора.

Причина: данные о клиенте и данные о заказе хранятся вместе.


Инцидент 3: Невозможно добавить магазин

Открывается новый магазин «МегаВосток» в Екатеринбурге. Но внести его в базу нельзя — таблица orders_flat хранит магазины только через заказы. Без заказа — нет строки. Нет строки — нет магазина.

Причина: сущность «магазин» не существует независимо.


Три типа аномалий

Все три инцидента — проявления классических аномалий:

АномалияИнцидентПотери
ОбновленияДвойная скидкаФинансовые
УдаленияПотеря историиОперационные
ВставкиНельзя добавить магазинБизнес-процессные

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

Правильная схема разделила бы данные по сущностям:

  • customers — покупатели
  • stores — магазины
  • orders — заказы (один заказ = одна строка)
  • order_items — позиции заказа

Тогда:

  • Скидка хранится в одном месте — в orders
  • Удаление покупателя не трогает финансовую историю
  • Магазин создаётся независимо от заказов

Именно это мы будем строить в этом модуле — шаг за шагом.

Прочитайте урок до конца — прогресс засчитается автоматически