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

Что дает третья форма нормализации

2.0 Middle🔥 71 комментариев
#Базы данных и SQL

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

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

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

Третья форма нормализации (3NF)

Третья форма нормализации (3NF) — это стандарт проектирования БД, который исключает транзитивные зависимости и обеспечивает логическую целостность данных. Понимание 3NF критично для Java-разработчиков, работающих с базами данных.

Определение 3NF

Таблица находится в 3NF, если:

  1. Она находится во второй нормальной форме (2NF)
  2. Все неключевые атрибуты зависят только от первичного ключа, не от других неключевых атрибутов

Такая зависимость называется транзитивной — когда атрибут B зависит от первичного ключа, но через атрибут A.

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

Рассмотрим таблицу сотрудников:

Employee (id, name, department_id, department_name, budget)

Здесь department_name и budget зависят от department_id, а не напрямую от id сотрудника. Это транзитивная зависимость:

id → department_id → department_name
id → department_id → budget

Проблемы при нарушении 3NF

1. Избыточность данных (Data Redundancy)

Если у нас 100 сотрудников в одном отделе, мы дублируем название и бюджет отдела 100 раз:

id | name      | department_id | department_name | budget
1  | Alice     | 10            | IT              | 500000
2  | Bob       | 10            | IT              | 500000
3  | Charlie   | 10            | IT              | 500000

2. Аномалии обновления (Update Anomalies)

Если нужно изменить бюджет отдела IT, нужно обновить 100 строк. Если забыть обновить одну, данные становятся несогласованными.

3. Аномалии удаления (Delete Anomalies)

Если удалить последнего сотрудника отдела, мы потеряем информацию об отделе:

employeeRepository.deleteById(3L); // Теперь информация об отделе IT потеряна

4. Аномалии вставки (Insert Anomalies)

Нельзя добавить новый отдел, пока не добавите сотрудника:

// Невозможно создать запись об отделе без сотрудника

Приведение к 3NF

Разделяем таблицу на две:

Таблица Employee:

id | name      | department_id
1  | Alice     | 10
2  | Bob       | 10
3  | Charlie   | 10

Таблица Department:

id | name    | budget
10 | IT      | 500000
20 | Sales   | 300000

Теперь нет транзитивных зависимостей. Все неключевые атрибуты зависят только от первичного ключа своей таблицы.

Преимущества 3NF

1. Устранение избыточности

Данные об отделе хранятся в одном месте.

2. Упрощение обновлений

@Transactional
public void updateDepartmentBudget(Long deptId, BigDecimal newBudget) {
    Department dept = departmentRepository.findById(deptId)
        .orElseThrow(() -> new NotFoundException("Department not found"));
    dept.setBudget(newBudget);
    departmentRepository.save(dept); // Одна строка обновляется
}

3. Обеспечение целостности данных

Отношение Foreign Key между Employee и Department гарантирует, что каждый сотрудник связан с существующим отделом.

4. Упрощение запросов

@Query("SELECT e FROM Employee e JOIN e.department d WHERE d.budget > :minBudget")
List<Employee> findEmployeesInHighBudgetDepartments(@Param("minBudget") BigDecimal minBudget);

Когда нарушать 3NF

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

  • Кэширование часто используемых данных
  • Агрегированные поля для сложных аналитических запросов
  • OLAP системы, где скорость чтения критичнее целостности

Но это исключения, а не правило. В большинстве случаев 3NF — это основа надёжной архитектуры БД.

Практический пример в Java

@Entity
@Table(name = "employees")
public class Employee {
    @Id
    private Long id;
    private String name;
    
    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;
}

@Entity
@Table(name = "departments")
public class Department {
    @Id
    private Long id;
    private String name;
    private BigDecimal budget;
    
    @OneToMany(mappedBy = "department")
    private List<Employee> employees;
}

3NF — это не просто теория БД, это практический инструмент для написания масштабируемых и надёжных Java-приложений.