Локальное развёртывание ИИ на архитектуре заказчикаЛюбая кастомизация и доработка бота
Главная / Блог / Нормализация данных: нормальные формы, примеры и денормализация
Статья

Нормализация данных: нормальные формы, примеры и денормализация

Нормализация данных: аномалии вставки, обновления и удаления, нормальные формы 1НФ, 2НФ, 3НФ и БКНФ с примерами, пошаговая нормализация таблицы продаж с SQL-кодом, денормализация и её компромиссы, сравнительная таблица форм и практические советы.

Нормализация данных: слева таблица продаж с дублирующимися строками, справа три связанные таблицы — Клиенты, Заказы и Товары

Нормализация данных — это процесс преобразования структуры реляционной базы данных для устранения избыточности и аномалий вставки, обновления и удаления. Цель — минимизировать дублирование данных и гарантировать целостность. Нормальные формы (1НФ, 2НФ, 3НФ, БКНФ) задают формальные условия качества схемы: каждая устраняет свои типы зависимостей и аномалий. Денормализация, наоборот, вводит контролируемую избыточность для ускорения чтения — за счёт худшего времени записи.

Ниже — назначение нормализации и аномалии, формальные определения нормальных форм с примерами, пошаговый разбор нормализации таблицы с SQL-кодом и схемой связей, а также причины, приёмы и компромиссы денормализации. В конце — сравнительная таблица нормальных форм и практические советы для разработчиков и администраторов БД.

Что такое нормализация данных и зачем она нужна

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

  • Аномалия вставки (Insert). Возникает, когда невозможно добавить новую запись без указания лишних данных: например, пока не создан заказ, нельзя завести информацию о товаре.
  • Аномалия обновления (Update). Проявляется, если при изменении данных в одном месте не обновляются все копии: например, имя клиента меняется только в одной строке, а в других остаётся старое.
  • Аномалия удаления (Delete). Если при удалении записи пропадает также связанная информация. Например, удалили последнего студента из группы — вместе с ним исчезли сведения о самой группе.

Ненормализованные таблицы обычно имеют дублирующиеся столбцы и сложные составные поля, что и приводит к описанным проблемам. Как пишет К. Дейт, общее назначение нормализации — исключение избыточности и устранение аномалий обновления. Проще говоря, нормализация упрощает проект БД и обеспечивает логическую консистентность данных при операциях INSERT/UPDATE/DELETE.

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

Нормальные формы (НФ) вводят строгие требования к схемам отношений. Каждая следующая НФ включает условия предыдущих и добавляет новые ограничения на функциональные зависимости (ФЗ) между столбцами.

Четыре ступени нормальных форм: 1НФ разбивает неатомарные значения, 2НФ убирает частичные зависимости от части ключа, 3НФ — транзитивные, БКНФ требует, чтобы все зависимости шли от ключа
Каждая следующая нормальная форма включает требования предыдущих: атомарность → полные зависимости → отсутствие транзитивности → все зависимости от ключа.

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

Отношение находится в 1НФ, если все атрибуты атомарны, то есть каждый столбец содержит неделимое значение — никаких списков или множеств. Практически это означает отсутствие повторяющихся групп и подтаблиц внутри одной записи. В терминах реляционной модели таблицы по определению находятся в 1НФ, но на практике в них встречаются неатомарные данные — например, столбец «Товары1, Товары2» или перечисление через запятую. При переходе в 1НФ такие многозначные поля устраняются, а данные разбиваются на строки.

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

Отношение в 2НФ, если оно уже в 1НФ и каждый неключевой атрибут функционально полностью зависит от всего потенциального ключа. Иначе говоря, если есть составной ключ, то ни один столбец не должен зависеть только от его части. Это исключает частичные зависимости. Например, в таблице (Заказ, Товар, ИмяКлиента) атрибут ИмяКлиента зависит только от Заказа — части ключа, что нарушает 2НФ. Перенос таких зависимостей в отдельные таблицы путём декомпозиции устраняет дублирование.

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

Отношение в 3НФ, если оно в 2НФ и нет транзитивных зависимостей неключевых атрибутов от ключа. Транзитивная зависимость — когда атрибут A → B → C, то есть A определяет B, а B — C. В таблице (Сотрудник, Департамент, Город), если Сотрудник → Департамент и Департамент → Город, то Город транзитивно зависит от Сотрудника. В 3НФ такая ситуация недопустима: нужно вынести зависимые атрибуты в отдельную таблицу — например, выделить таблицу «Департаменты». Таким образом 3НФ устраняет зависимость «ключ → неключ → неключ», улучшая целостность.

Нормальная форма Бойса — Кодда (БКНФ)

Это усиленная 3НФ: отношение в БКНФ, если для каждой нетривиальной ФЗ X → Y детерминант X является надключом — то есть содержит некоторый кандидатный ключ. Иначе говоря, любая зависимость идёт только от ключа. БКНФ устраняет случаи, когда несколько кандидатов на ключ «пересекаются» в зависимостях. На практике 3НФ часто достаточно, но если обнаруживается зависимость, нарушающая БКНФ, требуется дополнительная декомпозиция.

Нормальные формы выше 3НФ (4НФ, 5НФ и так далее) связаны с мультизависимостями и проекционно-соединительными зависимостями; они применяются в очень специфических ситуациях — например, при сложных алгебраических разбиениях. Обычно же задачи OLTP-систем ограничиваются 3НФ и БКНФ.

Пример нормализации: шаг за шагом

Рассмотрим конкретный пример. Пусть изначально есть денормализованная таблица продаж SalesDenorm, где хранятся данные о заказах:

CREATE TABLE SalesDenorm (
    order_id    INT,
    customer    VARCHAR(50),
    city        VARCHAR(50),
    product_id  INT,
    product     VARCHAR(100),
    quantity    INT
);

INSERT INTO SalesDenorm VALUES
  (1, 'Иван', 'Москва', 101, 'Ноутбук', 1),
  (1, 'Иван', 'Москва', 102, 'Монитор', 2),
  (2, 'Пётр', 'СПб',    101, 'Ноутбук', 1);

Здесь ключ таблицы — составной (order_id, product_id). Заметим несколько нарушений: атрибуты customer, city зависят только от order_id, а product — только от product_id. Это частичные зависимости относительно ключа, то есть таблица не находится во 2НФ. Начнём нормализацию.

Шаг 1. 1НФ

Таблица уже в 1НФ — никаких множеств в полях нет. Если бы, например, товары в заказе были записаны через запятую в одном столбце, мы бы вынесли каждую пару (order_id, product) в отдельную строку. Здесь позиции заказа уже разнесены по строкам, так что условие 1НФ выполняется.

Шаг 2. 2НФ

Устраняем частичные зависимости от частей ключа: customer, city зависят только от order_id, а product — только от product_id. Разобьём на три таблицы:

-- Таблица заказов (номер заказа и информация о клиенте)
CREATE TABLE Orders (
    order_id  INT PRIMARY KEY,
    customer  VARCHAR(50),
    city      VARCHAR(50)
);

-- Таблица продуктов (ID продукта и название)
CREATE TABLE Products (
    product_id INT PRIMARY KEY,
    product    VARCHAR(100)
);

-- Таблица «позиции заказа» с количеством
CREATE TABLE OrderItems (
    order_id   INT,
    product_id INT,
    quantity   INT,
    PRIMARY KEY (order_id, product_id),
    FOREIGN KEY (order_id) REFERENCES Orders(order_id),
    FOREIGN KEY (product_id) REFERENCES Products(product_id)
);

-- Заполняем новые таблицы из исходных данных
INSERT INTO Orders (order_id, customer, city)
    SELECT DISTINCT order_id, customer, city FROM SalesDenorm;
INSERT INTO Products (product_id, product)
    SELECT DISTINCT product_id, product FROM SalesDenorm;
INSERT INTO OrderItems (order_id, product_id, quantity)
    SELECT order_id, product_id, quantity FROM SalesDenorm;

В результате таблица OrderItems уже находится во 2НФ: все неключевые атрибуты (quantity) функционально зависят от всего ключа, а зависимые от частей ключа переместились в Orders и Products.

Шаг 3. 3НФ

Проверим транзитивные зависимости. В нашем примере их нет: в таблице Orders ключ — order_id, и customer, city зависят прямо от него; в Products ключ product_id, атрибут product — тоже напрямую. Таким образом каждая таблица уже в 3НФ. Можно дополнительно отметить, что все наши таблицы удовлетворяют и БКНФ, поскольку в них у любой функциональной зависимости левый атрибут — ключ.

Таким образом из одной исходной таблицы мы выделили три, тем самым устранили избыточность данных. Изначально информация о клиенте «Иван, Москва» хранилась дважды — для двух позиций заказа. После нормализации она хранится один раз в таблице Orders.

Схема связей после нормализации: сущность Orders связана с OrderItems типом «один ко многим» (один заказ может иметь много позиций), а Products — с OrderItems также «один ко многим» (каждый товар может входить во многие заказы). Такая структура исключает описанные аномалии.

ER-схема после нормализации: таблицы Orders и Products связаны с таблицей OrderItems отношением один ко многим, составной ключ order_id и product_id
Схема после декомпозиции: OrderItems связывает заказы и товары составным ключом (order_id, product_id).

Денормализация: зачем, когда и как

Денормализация — это осознанное введение избыточности в уже нормализованную схему ради повышения производительности. Когда база данных обслуживает огромное число запросов чтения (BI-платформы, аналитика) и несколько таблиц часто соединяются JOIN, нормализация может замедлить выполнение запросов. Денормализация ускоряет такие запросы за счёт избежания сложных объединений и дополнительных вычислений. Типичные приёмы:

  • Дублирование столбцов. Добавление в таблицу столбца, содержащего данные из связанной таблицы — например, сохранить city клиента прямо в таблице заказов.
  • Сохранение агрегатов. Вычисление и хранение промежуточных сумм или статистик: например, столбец total_amount в заказе вместо расчёта SUM(quantity * price) при каждом запросе.
  • Объединённые таблицы (снижение числа JOIN). Создание материализованного представления или таблицы, в которой объединены связанные данные. Классический пример — звёздная схема: таблица фактов плюс размерности.
  • Предвычисленные выражения. Хранение результата сложных вычислений, используемых во множественных запросах.
Нормализация против денормализации: слева много связанных таблиц и быстрая запись, справа одна широкая таблица с избыточностью и быстрое чтение
Размен: нормализованная схема выигрывает на записи и целостности, денормализованная — на чтении.

Причиной для денормализации чаще всего является скорость обработки запросов: денормализованные таблицы позволяют избежать нескольких объединений и агрегатных операций, что в ряде СУБД даёт существенный выигрыш в производительности. Однако следует помнить о компромиссах: избыточность усложняет поддержание целостности. Если у вас появились дубликаты данных, при изменении одной копии придётся обновлять все остальные — иначе БД разойдётся. В базе создаются дополнительные ограничения (триггеры, обновляемые представления) на синхронизацию копий, но это увеличивает сложность схемы и замедляет операции INSERT/UPDATE/DELETE.

Пример. Предположим, есть таблица Customers (ID, имя, город) и часто нужно получать число заказов каждого клиента. Можно добавить в Customers столбец order_count, в котором хранится число заказов. Запросы «получить имя клиента и число заказов» станут быстрыми — без объединения с таблицей заказов, — но нужно поддерживать order_count при каждой вставке или удалении заказа. Это классический пример денормализации: выигрыш в чтении ценой усложнённой логики записи.

Итак, денормализация улучшает время ответа SELECT за счёт хранения уже объединённых или агрегированных данных, но увеличивает избыточность. Поэтому она уместна в ситуациях с частыми чтениями большого объёма данных — например, в хранилищах данных и аналитике. Стандартные техники: добавление избыточных столбцов, создание обобщённых таблиц (звёздные схемы), предкомпилированных срезов и кубов. Нужно помнить о компенсационных мерах (constraints, проверки) во избежание рассинхронизации и о том, что современные системы всё чаще жертвуют избыточным хранением ради скорости запросов.

Сравнительная таблица нормальных форм

Нормальная формаОсновное условиеУстраняет / избегаетПример эффекта
1НФКаждый атрибут — атомарное (неделимое) значениеМногозначные поля, повторяющиеся группыТаблица без вложенных списков и подтаблиц
2НФВ 1НФ + полные зависимости: все неключевые атрибуты полностью зависят от ключаЧастичные зависимости от части ключаПеренос данных о клиенте в отдельную таблицу заказов
3НФВ 2НФ + отсутствуют транзитивные зависимостиТранзитивные зависимости (ключ → A → B)Выделение таблицы «Департаменты» вместо колонки в таблице «Сотрудники»
БКНФДля любой ФЗ X → Y левый атрибут X — надключ (содержит ключ)Любые зависимости от неключей (строже 3НФ)Гарантия, что каждая зависимость идёт от ключа

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

Нормализация в анализе данных и машинном обучении

Тем же словом называют принципиально другую операцию: приведение числовых признаков к общему масштабу. Структура данных при этом не меняется — меняются значения. Цель — чтобы алгоритм не считал «выручку в рублях» важнее «количества обращений» просто из-за порядка чисел.

  • Min-max нормализация: x' = (x − min) / (max − min) — приводит значения к диапазону [0; 1]. Чувствительна к выбросам: один аномальный максимум сжимает остальную выборку.
  • Z-оценка (стандартизация): z = (x − μ) / σ — среднее 0, стандартное отклонение 1. Диапазон не ограничен, зато устойчивее к выбросам.
  • Robust scaling: x' = (x − median) / IQR — на медиане и межквартильном размахе, рабочий вариант при «грязных» данных.
  • Логарифмирование: x' = log(1 + x) — не масштабирование в строгом смысле, но обязательный приём для величин с тяжёлым хвостом: сумм чеков, длительностей.

Масштабирование нужно методам, которые считают расстояние или используют градиентный спуск: KNN, SVM, линейные и логистические модели с регуляризацией, нейросети, PCA, k-means. Решающим деревьям, случайному лесу и градиентному бустингу (CatBoost, XGBoost, LightGBM) оно не нужно — они работают с порядком значений, а не с их масштабом.

Главная ошибка здесь — утечка данных. Параметры преобразования (минимум, максимум, среднее, стандартное отклонение) считают только на обучающей выборке и затем применяют к валидационной и тестовой. Если посчитать их на всём датасете, метрики на валидации окажутся завышенными, а в продакшене модель просядет. Сохранённый scaler — часть артефакта модели, а не разовый шаг в ноутбуке.

Практические советы по нормализации

  • Документируйте зависимости. Чётко фиксируйте функциональные зависимости между атрибутами. Перед проектированием сделайте ER-диаграмму, чтобы увидеть ключи и зависимости.
  • Начинайте с 3НФ. Стремитесь сразу привести схемы в 3НФ или БКНФ, чтобы избежать базовых аномалий. Проверьте на полноту зависимостей: если видите частичную или транзитивную зависимость, разнесите атрибуты по таблицам.
  • Используйте суррогатные ключи. Вместо естественных составных ключей часто проще ввести искусственный автоинкрементный ключ (ID). Это упрощает ссылки и часто помогает при нормализации, особенно в сложных связях.
  • Следите за изменениями схемы. При добавлении или удалении столбцов пересматривайте нормализацию: новые атрибуты могут нарушить нормальные формы.
  • Балансируйте с производительностью. Нормализация улучшает целостность, но может сделать JOIN-запросы более дорогими. Профилируйте запросы и при необходимости добавляйте индексы или денормализуйте «горячие» части схемы. В PostgreSQL, например, материализованные представления сами по себе являются формой денормализации.
  • Проверяйте схемы СУБД. Некоторые СУБД (PostgreSQL, MySQL) неявно ожидают, что таблицы находятся в 1НФ и 2НФ. Убедитесь, что ограничения целостности (PRIMARY KEY, FOREIGN KEY, UNIQUE) определены правильно — они часто выявляют нарушения нормальных форм при попытке вставить «неправильные» данные.
  • Минимизируйте NULL и повторяющиеся группы. Если в таблице много полей со значением NULL или с многоуровневыми данными (массивами), рассмотрите нормализацию. Отношения должны быть простыми.
  • Учитывайте особенности предметной области. Иногда фактические связи противоречат формальным требованиям: наследование типов (специализация сущностей) или многозначные атрибуты. В таких случаях используйте расширенные модели (например, ДКНФ) или гибридные подходы — но осознавайте последствия.

Короткий ответ: три разных смысла одного термина

Одним словом «нормализация» называют три операции. В базе данных нормализуют структуру — раскладывают таблицы по нормальным формам. В машинном обучении нормализуют значения — приводят признаки к общему масштабу. В корпоративных системах нормализуют справочники — приводят номенклатуру, контрагентов и адреса к эталону. Схема может быть в безупречной 3НФ и при этом содержать три карточки одного болта.

Нормализация справочников и НСИ

В 1С, ERP и CRM «нормализовать данные» чаще всего означает именно это. Типовые объекты:

  • номенклатура: разнобой в наименованиях и единицах измерения, дубли после интеграций;
  • контрагенты: ИНН и КПП с пробелами и буквами-омоглифами, разные ОПФ одного юрлица;
  • адреса: свободный текст вместо кода ФИАС или ГАР, сокращения «ул./улица»;
  • телефоны и почты: нет канонического формата E.164, несколько значений в одном поле;
  • даты и суммы: текстовые поля, локальные разделители, валюта в поле суммы.

Рабочая последовательность: канонический формат для каждого атрибута → правила приведения → словарь синонимов → нечёткое сопоставление → эталонная запись (golden record) → валидация на входе. Последний шаг критичен: разовая чистка без валидации деградирует за один-два квартала.

Что даёт нормализация при внедрении ИИ

СценарийЧто ломается на ненормализованных данных
RAG по документамОдин регламент в трёх версиях — поиск вернёт все три, модель выберет случайную
Агент над базой, text-to-SQL«Широкая» таблица без внешних ключей снижает долю корректных запросов
Прогнозы и аналитикаДубли номенклатуры размазывают спрос по нескольким карточкам одного товара
Дообучение моделиДубли и неоднородная разметка в датасете дают переоценку качества на валидации

Как устроен поиск по корпоративным документам — в разборе RAG. Как дать модели доступ к учётной системе, не отдавая данные наружу — в статье про MCP-серверы для 1С. Подготовка корпуса под дообучение — в материале про fine-tuning LLM в России. Если данные не должны покидать периметр — развёртывание on-premise и закрытый контур. Оценить готовность процессов до старта пилота помогает чек-лист руководителя.

Частые вопросы

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

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

Зачем нормализовать базу данных, если это может замедлить запросы?

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

Чем отличаются 2НФ и 3НФ?

2НФ устраняет частичные зависимости: все неключевые атрибуты должны зависеть от всего составного ключа. 3НФ дополнительно убирает транзитивные зависимости, когда неключевые атрибуты зависят друг от друга через ключ. Проще: 3НФ строже, чем 2НФ, и гарантирует, что между неключевыми столбцами нет скрытых зависимостей.

Что такое транзитивная зависимость?

Это когда столбец C зависит от столбца B, а B — от ключа. Тогда C косвенно зависит от ключа через B. Классический пример: в таблице (ID, Город, Регион), если ID → Город и Город → Регион, то ID транзитивно определяет Регион. В 3НФ Регион нужно вынести в отдельную сущность.

Что такое БКНФ и когда она нужна?

БКНФ (нормальная форма Бойса — Кодда) — строгая версия 3НФ: все функциональные зависимости исходят от надключа. Она нужна в редких случаях, когда в 3НФ-таблице есть «перекрывающиеся» кандидаты на ключ, приводящие к аномалиям. В большинстве практических задач 3НФ покрывает необходимые требования.

Сколько существует нормальных форм?

Основных шесть — с 1НФ по 6НФ, плюс нормальная форма Бойса — Кодда между 3НФ и 4НФ и доменно-ключевая (ДКНФ) как теоретический предел. Формы вложены: таблица в 3НФ автоматически находится во 2НФ и 1НФ. На практике реляционные схемы проектируют до 3НФ или БКНФ.

Когда использовать денормализацию?

Денормализация оправдана, если система подвергается большим нагрузкам чтения и часто выполняет сложные JOIN или агрегатные запросы: аналитические отчёты, OLAP-хранилища, звёздные схемы, кеширование результатов. Помните, что при этом пишется больше кода поддержки, а операции записи становятся медленнее — избыточные данные нужно обновлять.

Чем нормализация в БД отличается от нормализации в машинном обучении?

В базе данных нормализуют структуру: таблицы декомпозируют по нормальным формам. В машинном обучении нормализуют значения — числовые признаки приводят к общему масштабу по формуле min-max x* = (x − min) / (max − min) или через z-оценку z = (x − μ) / σ. Структура данных при этом не меняется.

Похожие посты

Все

Остались вопросы?

Отправьте заявку и наш специалист свяжется с вами в ближайшее время и проконсультирует по всем вопросам.

Нормализация данных: нормальные формы и примеры | Роботок