Нормализация данных
Зачем нормализовать
Нормализация устраняет избыточность и аномалии обновления при проектировании таблиц. Цель — согласованность данных, а не максимальная скорость чтения. Производительность при необходимости восстанавливают денормализацией с явным контролем дублирования.
Функциональные зависимости
Определение: атрибут B функционально зависит от A (A → B), если каждому значению A соответствует ровно одно значение B.
| Тип | Пример |
|---|---|
| Тривиальная | {сотрудник, отдел} → сотрудник |
| Полная | B зависит от всего составного ключа, не от его части |
| Частичная | B зависит только от части составного ключа |
| Транзитивная | A → B, B → C, при этом B не является ключом |
Отношение с простым (не составным) первичным ключом автоматически находится во 2НФ: частичных зависимостей от части ключа быть не может.
Нормальные формы
1НФ — первая нормальная форма
Критерий: все значения атомарны — нет массивов в ячейке, повторяющихся групп столбцов (телефон1, телефон2) и вложенных структур без отдельной таблицы.
2НФ — вторая нормальная форма
Критерий: 1НФ выполнена, и каждый неключевой атрибут полностью зависит от первичного ключа.
Нарушение: составной ключ (order_id, product_id), а атрибут product_name зависит только от product_id.
Исправление: вынести товар в отдельное отношение products.
3НФ — третья нормальная форма
Критерий: 2НФ выполнена, и неключевые атрибуты нетранзитивно зависят от ключа.
Нарушение: employee_id → department_id → department_head в одной таблице сотрудников.
Исправление: таблица departments(department_id, department_head, ...).
Аномалии обновления
| Аномалия | Проявление |
|---|---|
| Вставки | Нельзя добавить отдел без сотрудника, если отдел хранится только в строке сотрудника |
| Удаления | Удаление последнего сотрудника стирает сведения об отделе |
| Модификации | Смена названия отдела требует обновления многих строк |
Нормализация разбивает данные так, чтобы каждый факт хранился в одном месте.
Практика: декомпозиция «Заказы»
Исходная денормализованная таблица (ключ — (order_id, product_code)):
Заказы (номер_заказа, дата, id_клиента, фио_клиента, телефон, город,
код_товара, наименование_товара, категория, цена, количество)
Зависимости:
order_id→date,client_idclient_id→full_name,phone,cityproduct_code→name,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;
- исторические срезы в хранилище данных.
Контрольные вопросы
- Почему таблица с простым первичным ключом автоматически во 2НФ?
- Приведите пример транзитивной зависимости вне иерархии «сущность — подчинённая сущность».
- Когда денормализация не приводит к аномалиям модификации?
- Почему 3НФ не устраняет все избыточности? (подсказка: НФ Бойса–Кодда)
См. также
- Реляционная модель данных
- Ограничения целостности в SQL
- Чек-лист самопроверки — пункты 15–16, 48
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Вот SQL как раз обеспечивает такую связь и это главное отличие реляционных БД - реляции (relations), что означает связи. Знакомимся с языком - ставим программы, запускаем, выполняем первые запросы. От файлового хранения к реляционной и современной мультимодельной СУБД — термины, причины появления SQL и базовая классификация систем. Домены, атрибуты, кортежи и отношения — свойства реляционных таблиц и ограничения целостности при проектировании схемы. Метаданные СУБД через information_schema и pg_catalog — запросы к структуре таблиц, ключей и индексов в PostgreSQL. Логическое и физическое резервное копирование, pg_dump, pg_restore, WAL и восстановление на точку во времени (PITR). Логический порядок выполнения SELECT, проекция, WHERE, DISTINCT, ORDER BY и правила читаемого форматирования запросов. Скалярные и коррелированные подзапросы, EXISTS против IN, особенности NULL и выбор между подзапросом и JOIN. AND, OR, NOT, приоритет операторов, NULL и UNKNOWN, IS NULL, NOT IN и IS DISTINCT FROM в PostgreSQL. MVCC, уровни блокировок таблиц, FOR UPDATE, SKIP LOCKED, взаимоблокировки и диагностика через pg_locks. Учебная схема интернет-магазина для PostgreSQL — DDL и примеры запросов по темам курса SQL. Принципы работы SQL-движка - подключение к СУБД, разбор и выполнение запроса и возврат результата клиенту.SQL - язык структурированных запросов
Первые шаги с SQL
Эволюция систем хранения данных
Реляционная модель данных
Словарь данных и системные каталоги
Резервное копирование и восстановление PostgreSQL
Оператор SELECT — синтаксис и стиль
Подзапросы, EXISTS и IN
Фильтрация и трёхзначная логика
Блокировки и конкурентный доступ в PostgreSQL
Практикум shop_data
Принципы работы SQL-движка