5NF and Database Design
Давайте разберёмся с пятой нормальной формой. Но сначала — признайтесь: вы когда-нибудь понимали 5NF с первого раза? Я — нет. И знаете почему? Потому что её объясняют так, будто специально запутывают.
Помню, как читал статью в Википедии про 5NF и думал: «Это вообще про что?» Там какой-то продавец продаёт бренды определённых типов товаров, и если он продаёт один бренд одного типа, то обязан продавать все комбинации — что-то совсем безумное. Бизнес-смысл? Ноль. Зато есть «строгая математика».
Сегодня расскажу, почему 5NF — это не магия, а простое следствие грамотного проектирования. И почему на самом деле вам она может не понадобиться.
Что такое пятая нормальная форма
Нормализация в базах данных — это процесс организации данных для устранения избыточности и аномалий. Есть несколько «форм» — от первой до пятой. Каждая следующая форма накладывает более строгие ограничения.
Пятая нормальная форма (5NF) говорит о том, что таблица не должна раскладываться на более простые таблицы без потери информации. Звучит умно, но на практике это означает: если вы правильно спроектировали связи между сущностями на уровне логической модели — вы уже получите 5NF «в подарок».
Проблема в том, что объяснения обычно начинают не с того конца. Показывают таблицу и спрашивают: «А что если мы её разделим?» Вместо того чтобы спросить: «А какую бизнес-задачу мы решаем?»
Два паттерна проектирования
Автор статьи Alexey Makhotkin выделяет два интересных паттерна, которые всплывают вокруг обсуждения 5NF:
Треугольник AB-BC-AC — три сущности связаны попарно, каждая связь «многие-ко-многим». Классический пример — мороженое.
Звезда ABC+D — центральная сущность связана с тремя другими особым образом. Пример — концерты и музыканты.
Разберём оба.
Пример с мороженым: треугольник
Вот понятный пример из статьи:
Есть бренды мороженого (Frosty’s, Alpine, Ice Queen). Каждый бренд производит несколько вкусов (ванильный, клубничный, шоколадный). У нас есть друзья, которые любят определённые бренды и определённые вкусы.
Самое важное условие: предпочтения друзей пересекаются. Если друг любит бренды A и B и вкусы 1 и 2 — значит, он любит все комбинации A-1, A-2, B-1 и B-2 (конечно, только те, которые бренд реально производит).
СУЩНОСТИ И СВЯЗИ ───────────────── Бренд ──────► Вкус │ ▲ ▼ │ Друг ◄─────────┘ Три связи M:N: • Бренд производит Вкус • Друг предпочитает Бренд • Друг предпочитает Вкус
Что происходит дальше? В классическом подходе к проектированию мы создаём три таблицы-связки (junction tables):
- `brand_flavours` (бренд → вкус)
- `friend_brands` (друг → бренд)
- `friend_flavours` (друг → вкус)
И отдельные таблицы для сущностей: `brands`, `flavours`, `friends`.
Это естественное следствие работы с M: N связями («многие-ко-многим»). Никакой магии 5NF здесь отдельно применять не надо — она получается автоматически.
Пример с музыкантами: звезда
Второй пример интереснее. Это случай из блога Data Demythed:
Мы хотим хранить информацию о концертах и музыкантах, которые играли на определённых инструментах.
Сущности:
- Концерт
- Инструмент
- Музыкант
Связи:
- Музыкант участвует в Концерте
- Музыкант умеет играть на Инструменте
- Музыкант играет на Инструменте на Концерте
Последняя связь здесь особая — она зависит от двух других. Это производная связь: чтобы узнать, кто играет на скрипке на рождественном концерте, нам нужно знать:
- Кто вообще участвует в этом концерте?
- Кто вообще умеет играть на скрипке?
Если оба условия выполняются — значит, музыкант играет.
ЗВЁЗДНЫЙ ПАТТЕРН ABC+D
───────────────────────
Концерт ───────┐
▼
Инструмент ◄── Музыкант ──► Концерт
▲ │
└──────────────┘
Играет на
(производная связь)
Вопрос: нужна ли отдельная таблица для третьей связи? Теоретически да — если мы хотим хранить дополнительные данные о самом выступлении (например, длительность соло). Но если нам нужна только информация «кто где играл» — можно обойтись без неё.
Так нужна ли вам 5nf?
Автор статьи приходит к интересному выводу: вам не нужно отдельно думать о пятой нормальной форме.
Всё просто:
- Начинаете с бизнес-требований → строите логическую модель
- Применяете стандартную стратегию проектирования таблиц → каждая сущность = таблица, каждая M: N связь = junction table
- Результат автоматически получается нормализованным
Проблема объяснения 5NF в том, что оно вывернуто наизнанку. Показывают готовую таблицу и спрашивают «а что если бы…?» вместо того чтобы спросить «какую задачу решаем?».
По сути пятая нормальная форма — это профессиональная гигиена проектирования. Как чистить зубы каждый день: не думаешь же каждый раз «сейчас буду делать гигиену полости рта» — просто делаешь.
Вывод
Если вы начинаете проектирование базы данных с логической модели и честно отвечаете на вопросы «какие сущности существуют?» и «как они связаны?» — вы автоматически получаете нормализованную схему.
Не нужно запоминать правила пятой формы отдельно. Нужно понимать предметную область и уметь рисовать связи между сущностями.
А запутанные примеры из Википедии можете забыть.
#
idea ──▶ draft ──▶ review ──▶ publish
Ссылки
- Блог Data Demythed: «5NF: The Missing Use Case» — рекомендую особенно раздел «In Conclusion»
- Видео Decomplexify про нормализацию — пример с мороженым
Дмитрий Полухин — продуктовый дизайнер. Пишу про разработку, AI и дизайн интерфейсов. Обо мне, контакты и профили.