Перейти к основному содержимому

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

Разработчику Аналитику Архитектору

Зачем нормализовать

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


Функциональные зависимости

Определение: атрибут B функционально зависит от A (AB), если каждому значению A соответствует ровно одно значение B.

ТипПример
Тривиальная{сотрудник, отдел}сотрудник
ПолнаяB зависит от всего составного ключа, не от его части
ЧастичнаяB зависит только от части составного ключа
ТранзитивнаяAB, BC, при этом B не является ключом

Отношение с простым (не составным) первичным ключом автоматически находится во 2НФ: частичных зависимостей от части ключа быть не может.


Нормальные формы

1НФ — первая нормальная форма

Критерий: все значения атомарны — нет массивов в ячейке, повторяющихся групп столбцов (телефон1, телефон2) и вложенных структур без отдельной таблицы.

2НФ — вторая нормальная форма

Критерий: 1НФ выполнена, и каждый неключевой атрибут полностью зависит от первичного ключа.

Нарушение: составной ключ (order_id, product_id), а атрибут product_name зависит только от product_id.

Исправление: вынести товар в отдельное отношение products.

3НФ — третья нормальная форма

Критерий: 2НФ выполнена, и неключевые атрибуты нетранзитивно зависят от ключа.

Нарушение: employee_iddepartment_iddepartment_head в одной таблице сотрудников.

Исправление: таблица departments(department_id, department_head, ...).


Аномалии обновления

АномалияПроявление
ВставкиНельзя добавить отдел без сотрудника, если отдел хранится только в строке сотрудника
УдаленияУдаление последнего сотрудника стирает сведения об отделе
МодификацииСмена названия отдела требует обновления многих строк

Нормализация разбивает данные так, чтобы каждый факт хранился в одном месте.


Практика: декомпозиция «Заказы»

Исходная денормализованная таблица (ключ — (order_id, product_code)):

Заказы (номер_заказа, дата, id_клиента, фио_клиента, телефон, город,
код_товара, наименование_товара, категория, цена, количество)

Зависимости:

  • order_iddate, client_id
  • client_idfull_name, phone, city
  • product_codename, category, price
  • (order_id, product_code)quantity

Итоговая схема в 3НФ:

CREATE TABLE clients (
client_id SERIAL PRIMARY KEY,
full_name TEXT NOT NULL,
phone TEXT,
city TEXT
);

CREATE TABLE products (
product_code VARCHAR(20) PRIMARY KEY,
name TEXT NOT NULL,
category TEXT,
price NUMERIC(10, 2) NOT NULL
);

CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
order_date DATE NOT NULL DEFAULT CURRENT_DATE,
client_id INT NOT NULL REFERENCES clients(client_id)
);

CREATE TABLE order_lines (
order_id INT NOT NULL REFERENCES orders(order_id),
product_code VARCHAR(20) NOT NULL REFERENCES products(product_code),
quantity INT NOT NULL CHECK (quantity > 0),
PRIMARY KEY (order_id, product_code)
);

Денормализация

Определение: сознательное нарушение нормальных форм ради других целей (скорость отчётов, меньше JOIN, витрины данных).

Допустима, если есть механизм согласованности: триггеры, периодическая пересборка, ETL.

Типичные сценарии:

  • аналитические запросы с десятками соединений;
  • высоконагруженное чтение в OLTP;
  • исторические срезы в хранилище данных.

Контрольные вопросы

  1. Почему таблица с простым первичным ключом автоматически во 2НФ?
  2. Приведите пример транзитивной зависимости вне иерархии «сущность — подчинённая сущность».
  3. Когда денормализация не приводит к аномалиям модификации?
  4. Почему 3НФ не устраняет все избыточности? (подсказка: НФ Бойса–Кодда)

См. также


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).