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

«Что такое нормализация и нормальные формы в базах данных?» — вопрос из категории SQL и базы данных, который задают на 33% собеседований Data Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Основные нормальные формы:

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

    • Все значения атрибутов атомарны (неделимы).
    • В таблице нет повторяющихся групп или массивов.
    • Пример нарушения: Столбец PhoneNumbers со значением "123-456, 789-012". Исправление: вынести номера в отдельную таблицу CustomerPhones.
  2. Вторая нормальная форма (2НФ):

    • Таблица находится в 1НФ.
    • Каждый неключевой атрибут полностью зависит от всего составного первичного ключа (а не от его части).
    • Пример: Таблица OrderDetails(OrderID, ProductID, ProductName, Quantity). ProductName зависит только от ProductID, а не от всей пары (OrderID, ProductID). Нарушение. Исправление: вынести ProductID, ProductName в таблицу Products.
  3. Третья нормальная форма (3НФ):

    • Таблица находится в 2НФ.
    • Нет транзитивных зависимостей. Неключевые атрибуты не должны зависеть от других неключевых атрибутов.
    • Пример: Таблица Employees(EmployeeID, DepartmentID, DepartmentLocation). DepartmentLocation зависит от DepartmentID, который не является ключом. Нарушение. Исправление: вынести DepartmentID, DepartmentLocation в таблицу Departments.

Практический пример преобразования:

-- Исходная денормализованная таблица (нарушает 1НФ, 2НФ, 3НФ)
CREATE TABLE CustomerOrders (
    OrderID INT,
    CustomerName VARCHAR(100),
    CustomerPhone VARCHAR(20), -- Зависит от CustomerName, а не от OrderID (3НФ)
    ProductID INT,
    ProductName VARCHAR(100), -- Зависит только от ProductID (2НФ)
    Quantity INT
    -- Первичный ключ? Составной (OrderID, ProductID)
);

-- Нормализованная схема (до 3НФ)
CREATE TABLE Customers (
    CustomerID INT PRIMARY KEY,
    CustomerName VARCHAR(100) NOT NULL,
    CustomerPhone VARCHAR(20)
);

CREATE TABLE Products (
    ProductID INT PRIMARY KEY,
    ProductName VARCHAR(100) NOT NULL
);

CREATE TABLE Orders (
    OrderID INT PRIMARY KEY,
    CustomerID INT NOT NULL,
    OrderDate DATE,
    FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID)
);

CREATE TABLE OrderDetails ( -- Разрешает составной PK для связи M:M
    OrderID INT NOT NULL,
    ProductID INT NOT NULL,
    Quantity INT NOT NULL,
    PRIMARY KEY (OrderID, ProductID),
    FOREIGN KEY (OrderID) REFERENCES Orders(OrderID),
    FOREIGN KEY (ProductID) REFERENCES Products(ProductID)
);

Зачем это нужно? Нормализация минимизирует дублирование, обеспечивает целостность данных и упрощает поддержку. Однако для сложных аналитических запросов (OLAP) часто применяется контролируемая денормализация для повышения скорости чтения за счет избыточности.