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

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

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

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

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

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

Нормализация Базы Данных

Нормализация — это процесс организации данных в базе данных с целью избежать дублирования, обеспечить целостность данных и оптимизировать производительность. Нормализация разбивает большие таблицы на меньшие, связанные между собой таблицы через иностранные ключи.

Зачем нужна нормализация

// ❌ Не нормализованная таблица — много проблем
CREATE TABLE orders (
    id INT,
    customer_name VARCHAR(100),
    customer_email VARCHAR(100),
    customer_phone VARCHAR(20),
    product_name VARCHAR(100),
    product_price DECIMAL(10,2),
    product_category VARCHAR(50),
    order_date DATE
);

// Проблемы:
// - Дублирование (один покупатель = много строк с теми же данными)
// - Аномалия обновления (изменил email в одной строке, забыл в другой)
// - Аномалия удаления (удалил заказ, потеряли инфо о покупателе)
// - Неправильное удаление (удалили последний заказ покупателя, потеряли его данные)

Нормальные формы (Normal Forms)

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

Требование: Все данные атомарные (неделимые), нет повторяющихся групп.

// ❌ Нарушает 1NF
CREATE TABLE users (
    id INT,
    name VARCHAR(100),
    phone_numbers VARCHAR(500) // "1234567, 9876543" — не атомарное!
);

// ✅ Соблюдает 1NF
CREATE TABLE users (
    id INT,
    name VARCHAR(100)
);

CREATE TABLE user_phones (
    id INT,
    user_id INT,
    phone_number VARCHAR(20),
    FOREIGN KEY (user_id) REFERENCES users(id)
);

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

Требование: 1NF + все неключевые атрибуты полностью зависят от первичного ключа (без частичных зависимостей).

// ❌ Нарушает 2NF
CREATE TABLE student_courses (
    student_id INT,
    course_id INT,
    professor_name VARCHAR(100), // зависит только от course_id, не от student_id!
    grade DECIMAL(3,2),
    PRIMARY KEY (student_id, course_id)
);

// ✅ Соблюдает 2NF
CREATE TABLE student_courses (
    student_id INT,
    course_id INT,
    grade DECIMAL(3,2),
    PRIMARY KEY (student_id, course_id),
    FOREIGN KEY (student_id) REFERENCES students(id),
    FOREIGN KEY (course_id) REFERENCES courses(id)
);

CREATE TABLE courses (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    professor_name VARCHAR(100)
);

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

Требование: 2NF + нет транзитивных зависимостей (неключевые атрибуты зависят только от первичного ключа).

// ❌ Нарушает 3NF
CREATE TABLE orders (
    id INT PRIMARY KEY,
    customer_id INT,
    customer_city VARCHAR(100),
    city_postal_code VARCHAR(10) // зависит от city, а не от order_id!
);

// ✅ Соблюдает 3NF
CREATE TABLE orders (
    id INT PRIMARY KEY,
    customer_id INT,
    city_id INT,
    FOREIGN KEY (customer_id) REFERENCES customers(id),
    FOREIGN KEY (city_id) REFERENCES cities(id)
);

CREATE TABLE cities (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    postal_code VARCHAR(10)
);

Нормализованная структура (пример e-commerce)

// ✅ Хорошо спроектированная БД
CREATE TABLE customers (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    email VARCHAR(100) UNIQUE,
    created_at TIMESTAMP
);

CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    price DECIMAL(10,2),
    category_id INT,
    FOREIGN KEY (category_id) REFERENCES categories(id)
);

CREATE TABLE categories (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100)
);

CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    customer_id INT,
    order_date DATE,
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);

CREATE TABLE order_items (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_id INT,
    product_id INT,
    quantity INT,
    price DECIMAL(10,2),
    FOREIGN KEY (order_id) REFERENCES orders(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

Преимущества нормализации

  • Избежать дублирования — каждое данное хранится один раз
  • Целостность данных — сложнее внести ошибку
  • Легче обновлять — меняешь данные в одном месте
  • Экономия места — нет дублирования
  • Быстрые запросы — правильная индексация

Недостатки нормализации

  • Сложные запросы — много джойнов, может быть медленно
  • Производительность — иногда денормализация быстрее
  • Сложность — больше таблиц, сложнее понять структуру

Денормализация (когда нужна)

Иногда для производительности делают частичную денормализацию — хранят закэшированные значения:

CREATE TABLE orders (
    id INT PRIMARY KEY,
    customer_id INT,
    total_amount DECIMAL(10,2), // закэшировано из order_items
    customer_name VARCHAR(100), // дублировано для быстрого доступа
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);