В реляционной модели один факт повторяется в нескольких строках. Как понять, что его нужно вынести в отдельную сущность?
Факт следует вынести в отдельную сущность, если он имеет собственную идентичность, жизненный цикл или изменяется независимо от строк, в которых сейчас повторяется. Главный критерий — устранение аномалий вставки, изменения и удаления без чрезмерного усложнения типичных запросов.
Нормализация возникла как способ уменьшить избыточность в реляционных моделях. Если один факт хранится в нескольких местах, изменение может обновить только часть копий, а удаление одной записи — случайно уничтожить сведения, которые ещё нужны системе.
Реляционный подход предлагает разделять независимые факты по сущностям и связывать их ключами. Это повышает согласованность данных, но может увеличить число соединений и сложность чтения.
Представим, что адрес поставщика хранится в каждой строке заказа. При смене адреса нужно изменить множество заказов, иначе исторические данные станут противоречивыми. Если удалить последний заказ поставщика, можно потерять самого поставщика как самостоятельный объект.
Повторение само по себе не всегда является ошибкой: иногда значение сознательно фиксируют как снимок на момент операции. Поэтому нужно отличать дублирование текущего факта от сохранения исторического состояния.
Сначала определяют функциональные зависимости: какие атрибуты однозначно определяются ключом строки, а какие зависят от другого объекта. Если атрибут поставщика определяется идентификатором поставщика, а не идентификатором заказа, его обычно следует хранить в сущности «Поставщик», а в заказе оставить ссылку на неё.
Признаки необходимости выделения сущности:
После разделения используют ссылочную связь и ограничения целостности. Это предотвращает ссылки на несуществующие объекты, но не решает автоматически вопрос историчности: для заказа может требоваться копия адреса на момент оформления, даже если текущий адрес поставщика изменился.
Компромисс выбирают по характеру чтения и записи. Нормализация уменьшает противоречия и стоимость массовых изменений, но требует соединений. Денормализация ускоряет конкретные чтения, однако требует чёткой стратегии обновления, контроля расхождений и понимания, какое значение является источником истины.
В системе доставки название тарифа и его стоимость хранились в каждой строке отправления. Рассматривались два варианта: оставить данные как есть для простых отчётов или вынести тариф в отдельную сущность. Первый вариант был проще для чтения, но изменение стоимости создавало риск частичного обновления, а удаление тарифа затрудняло создание новых отправлений.
Выбрали отдельную сущность тарифа со ссылкой из отправления, а применённую стоимость сохранили в самой отправлении как исторический снимок. Так текущие параметры тарифа изменяются в одном месте, а финансовый результат уже оформленной отправки не меняется задним числом. Отдельное ограничение запретило удаление тарифа, если он используется в новых операциях; для архивных случаев применялся статус неактивности.
1. Всегда ли повторение значения означает нарушение нормализации?
Нет. Повторение может быть намеренным снимком состояния или производным значением для ускорения чтения. Важно определить семантику: если значение должно отражать текущий объект, копии опасны; если оно описывает прошлое состояние операции, копия может быть обязательна.
2. Что важнее при выборе между нормализацией и денормализацией?
Нельзя выбирать только по количеству таблиц или соединений. Нужно оценить частоту чтения и записи, требования к согласованности, допустимую задержку обновления, объём данных и способ восстановления расхождений. Денормализация оправдана, когда выигрыш измерим, а источник истины и процесс синхронизации явно определены.
3. Достаточно ли внешнего ключа для защиты от противоречий?
Нет. Внешний ключ проверяет существование связанной записи, но не гарантирует корректность бизнес-правил, уникальность комбинаций или допустимость перехода состояния. Дополнительно могут потребоваться уникальные ограничения, проверки, транзакционная обработка и валидация на уровне предметной логики.