← Назад к вопросам

Какие уровни нормализации существуют

1.0 Junior🔥 141 комментариев
#Базы данных и SQL#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Уровни нормализации БД (Database Normalization Forms)

Нормализация — это процесс организации данных в реляционной БД для минимизации избыточности и повышения целостности данных. Существует несколько уровней (форм) нормализации, каждый из которых решает определённые проблемы.

Ненормализованная форма (Unnormalized)

Проблемы:

  • Повторяющиеся группы данных в одном поле
  • Сложность обновлений и удаления данных
  • Потеря целостности данных

Пример ненормализованной таблицы:

| student_id | name  | courses                        |
|------------|-------|--------------------------------|
| 1          | John  | Math, Physics, Chemistry       |
| 2          | Jane  | Biology, Chemistry             |

Проблема: courses — это список в одном поле!

Первая Нормальная Форма (1NF)

Требования:

  • Все значения должны быть атомарными (неделимыми)
  • Нет повторяющихся групп
  • Каждая строка должна быть уникальна

Преобразование в 1NF:

| student_id | name | course    |
|------------|------|-----------|
| 1          | John | Math      |
| 1          | John | Physics   |
| 1          | John | Chemistry |
| 2          | Jane | Biology   |
| 2          | Jane | Chemistry |

SQL пример:

-- ❌ Не 1NF
CREATE TABLE students (
  student_id INT PRIMARY KEY,
  name VARCHAR(100),
  courses TEXT -- "Math, Physics, Chemistry"
);

-- ✅ 1NF
CREATE TABLE students (
  student_id INT PRIMARY KEY,
  name VARCHAR(100)
);

CREATE TABLE enrollments (
  enrollment_id INT PRIMARY KEY,
  student_id INT,
  course VARCHAR(100),
  FOREIGN KEY (student_id) REFERENCES students(student_id)
);

Вторая Нормальная Форма (2NF)

Требования:

  • Должна быть в 1NF
  • Все неключевые атрибуты должны полностью зависеть от первичного ключа (no partial dependency)
  • Нет частичной зависимости от составного ключа

Пример нарушения 2NF:

| student_id | course_id | course_name | instructor |
|------------|-----------|-------------|------------|
| 1          | 101       | Math        | Dr. Smith  |
| 1          | 102       | Physics     | Dr. Johnson|
| 2          | 101       | Math        | Dr. Smith  |

Проблема: course_name и instructor зависят только от course_id, а не от составного ключа (student_id, course_id)!

Решение 2NF:

CREATE TABLE students (
  student_id INT PRIMARY KEY,
  name VARCHAR(100)
);

CREATE TABLE courses (
  course_id INT PRIMARY KEY,
  course_name VARCHAR(100),
  instructor VARCHAR(100)
);

CREATE TABLE enrollments (
  student_id INT,
  course_id INT,
  PRIMARY KEY (student_id, course_id),
  FOREIGN KEY (student_id) REFERENCES students(student_id),
  FOREIGN KEY (course_id) REFERENCES courses(course_id)
);

Третья Нормальная Форма (3NF)

Требования:

  • Должна быть в 2NF
  • Нет транзитивной зависимости (non-key attributes не должны зависеть друг от друга)
  • Все неключевые атрибуты должны зависеть только от первичного ключа

Пример нарушения 3NF:

| employee_id | name  | department_id | department_name | location   |
|-------------|-------|---------------|-----------------|------------|
| 1           | John  | 10            | Engineering     | Building A |
| 2           | Jane  | 10            | Engineering     | Building A |
| 3           | Bob   | 20            | Sales           | Building B |

Проблема: department_name и location зависят от department_id, а не от employee_id!

Решение 3NF:

CREATE TABLE employees (
  employee_id INT PRIMARY KEY,
  name VARCHAR(100),
  department_id INT,
  FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

CREATE TABLE departments (
  department_id INT PRIMARY KEY,
  department_name VARCHAR(100),
  location VARCHAR(100)
);

Нормальная Форма Бойса-Кодда (BCNF)

Требования:

  • Должна быть в 3NF
  • Каждый детерминант (атрибут, от которого что-то зависит) должен быть кандидатом на первичный ключ
  • Более строгая версия 3NF

Редкое нарушение BCNF:

| student | professor | course          |
|---------|-----------|-----------------|
| John    | Dr. Smith | Database Design |
| Jane    | Dr. Smith | Database Design |
| Bob     | Dr. Jones | Web Development |

Если один профессор может преподавать только один курс, но таблица позволяет нарушить это правило.

Решение BCNF:

CREATE TABLE professor_courses (
  professor VARCHAR(100),
  course VARCHAR(100),
  PRIMARY KEY (professor, course),
  UNIQUE (professor)  -- Один профессор - один курс
);

CREATE TABLE classes (
  student VARCHAR(100),
  professor VARCHAR(100),
  course VARCHAR(100),
  PRIMARY KEY (student, professor),
  FOREIGN KEY (professor, course) REFERENCES professor_courses(professor, course)
);

Четвёртая и Пятая Нормальные Формы (4NF, 5NF)

4NF (Fourth Normal Form):

  • Разделяет независимые многозначные зависимости
  • Решает проблемы с несколькими независимыми one-to-many связями

5NF (Fifth Normal Form / PJNF):

  • Разделяет все зависимости на соединение
  • Самая строгая форма

Эти формы редко применяются на практике.

Практический пример: E-Commerce

Ненормализованная версия:

| order_id | customer_name | email           | items                              |
|----------|---------------|-----------------|------------------------------------|
| 1        | John Smith    | john@example.com| Laptop(1000), Mouse(25), USB(10)  |

1NF - Атомарные значения:

| order_id | customer_name | email            | item_name | price |
|----------|---------------|------------------|-----------|-------|
| 1        | John Smith    | john@example.com | Laptop    | 1000  |
| 1        | John Smith    | john@example.com | Mouse     | 25    |
| 1        | John Smith    | john@example.com | USB       | 10    |

2NF - Убрать частичные зависимости:

customers:
| customer_id | name      | email            |
|-------------|-----------|------------------|
| 1           | John Smith| john@example.com |

orders:
| order_id | customer_id |
|----------|-------------|
| 1        | 1           |

items:
| item_id | item_name | price |
|---------|-----------|-------|
| 101     | Laptop    | 1000  |
| 102     | Mouse     | 25    |
| 103     | USB       | 10    |

order_items:
| order_id | item_id |
|----------|---------|
| 1        | 101     |
| 1        | 102     |
| 1        | 103     |

3NF - Убрать транзитивные зависимости:

customers:
| customer_id | name       | city_id |
|-------------|------------|---------|
| 1           | John Smith | 5       |

cities:
| city_id | city_name | country |
|---------|-----------|---------|
| 5       | New York  | USA     |

orders:
| order_id | customer_id |
|----------|-------------|
| 1        | 1           |

items:
| item_id | item_name | category_id |
|---------|-----------|-------------|
| 101     | Laptop    | 1           |

categories:
| category_id | category_name |
|-------------|---------------|
| 1           | Electronics   |

order_items:
| order_id | item_id |
|----------|---------|
| 1        | 101     |

Денормализация (когда это допустимо)

Иногда нормализация может привести к проблемам производительности. Денормализация допустима для:

  • High-read scenarios — кэширование часто используемых данных
  • OLAP системы — Data Warehouses
  • Performance-critical — когда JOIN's медленнее, чем хранение дублированных данных
-- ❌ Медленно - 3 JOIN'а для каждого заказа
SELECT o.order_id, c.name, s.status, s.status_description
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
JOIN statuses s ON o.status_id = s.status_id;

-- ✅ Быстро - денормализация для Performance
-- Храним customer_name и status_description в orders
ALTER TABLE orders ADD COLUMN customer_name VARCHAR(100);
ALTER TABLE orders ADD COLUMN status_description VARCHAR(255);

SELECT order_id, customer_name, status_description
FROM orders;  -- Один запрос вместо 3 JOIN'ов

Best Practices

  1. Нормализуй до 3NF по умолчанию - оптимальный баланс между целостностью и производительностью
  2. Не денормализуй без явной необходимости - профилируй сначала
  3. Документируй причины денормализации - должна быть веская причина
  4. Используй views для логического объединения - вместо физического дублирования данных
  5. Тестируй целостность данных - при денормализации требуются триггеры и проверки

Вывод: Нормализация — фундаментальный принцип проектирования БД. Большинство production систем используют 3NF как оптимальный уровень. BCNF, 4NF и 5NF редко применяются на практике. Помни, что нормализация — это не догма, а инструмент для создания гибких, поддерживаемых, целостных систем.

Какие уровни нормализации существуют | PrepBro