Нормалізація бази даних: усунення надмірності та захист цілісності

Нормалізація бази даних — це систематичний процес декомпозиції таблиць на основі функціональних залежностей, який усуває логічну надмірність і запобігає аномаліям оновлення, вставки та видалення. Вона перетворює неохайну структуру з повторюваними значеннями на набір пов’язаних відношень, де кожен факт зберігається лише один раз.

Цей підхід, започаткований Едгаром Коддом у 1970 році, залишається основою проєктування реляційних систем і в 2026 році. Правильно нормалізована схема гарантує узгодженість даних навіть за інтенсивних змін і спрощує підтримку цілісності на рівні обмежень первинних і зовнішніх ключів.

Для початківців процес виглядає як послідовне застосування правил нормальних форм. Для досвідчених розробників він стає інструментом балансування між чистотою моделі та продуктивністю запитів у великих системах.

Чому функціональні залежності визначають усю логіку процесу

В основі нормалізації лежить поняття функціональної залежності. Якщо значення атрибута A однозначно визначає значення атрибута B, кажуть, що B функціонально залежить від A (записується A → B). Детермінант — це ліва частина такої залежності.

Коли в одній таблиці існують залежності, які не спираються на весь первинний ключ, виникає надмірність. Одне й те саме значення зберігається в багатьох рядках. Зміна адреси клієнта вимагає оновлення десятків записів. Якщо хоча б один рядок залишиться старим, з’являється аномалія оновлення. Аналогічно працюють аномалії вставки (неможливо додати інформацію про товар без замовлення) та видалення (видалення останнього замовлення знищує дані про клієнта).

Процес нормалізації полягає в тому, щоб кожна нетривіальна функціональна залежність мала детермінант, який є потенційним ключем. Саме це правило поступово втілюється в нормальних формах. У нашій практиці ми стикалися з випадком, коли таблиця замовлень містила одночасно дані клієнта, адресу доставки та список товарів у вигляді рядка з комами. Після виявлення залежностей «код клієнта → адреса» і «код товару → назва» таблицю розбили на три, і кількість помилок синхронізації впала майже до нуля.

Ключова ідея: нормалізація не зменшує фізичний обсяг даних за будь-яку ціну. Її мета — мінімізувати логічну надмірність, щоб кожен факт існував у системі лише в одному місці.

Покроковий перехід через нормальні форми з конкретними прикладами

Розглянемо класичну таблицю замовлень інтернет-магазину, яка ще не нормалізована.

Ненормалізована структура містить поля: номер_замовлення, дата, ім’я_клієнта, адреса_клієнта, телефон, назва_товару, кількість, ціна, категорія_товару. В одному рядку може бути кілька товарів, записаних через кому.

Перша нормальна форма (1НФ) вимагає атомарності значень і відсутності повторюваних груп. Кожна клітинка повинна містити одне неподільне значення, а кожен рядок — унікальний. Таблицю розбивають так, щоб кожен товар замовлення став окремим рядком. З’являється складений ключ (номер_замовлення + код_товару).

Друга нормальна форма (2НФ) додає вимогу повної функціональної залежності. Жоден неключовий атрибут не може залежати лише від частини складеного ключа. Адреса клієнта залежить тільки від номера замовлення, а не від товару. Тому дані клієнта виносять в окрему таблицю «Клієнти», а дані товару — в «Товари». Зв’язок забезпечують зовнішні ключі.

Третя нормальна форма (3НФ) усуває транзитивні залежності. Якщо категорія_товару залежить від назви_товару, а назва_товару — від коду_товару, то категорію треба винести в окрему таблицю. У 3НФ кожен неключовий атрибут залежить безпосередньо від первинного ключа і ні від чого більше.

Нормальна форма Бойса–Кодда (НФБК) посилює вимогу: кожен детермінант будь-якої функціональної залежності має бути потенційним ключем. У більшості практичних схем 3НФ уже задовольняє НФБК. Винятки виникають лише за наявності кількох перекривних кандидатських ключів.

Четверта і п’ята нормальні форми працюють із багатозначними залежностями та залежностями з’єднання. Вони потрібні рідко — переважно в складних системах з множинними незалежними множинами значень.

Нормальна форма Основна вимога Що усуває Типовий результат
1НФ Атомарні значення, відсутність повторюваних груп Багатозначні атрибути Окремий рядок на кожне значення
2НФ Повна залежність від усього ключа Часткові залежності Окремі таблиці для частин ключа
3НФ Відсутність транзитивних залежностей Залежності між неключовими атрибутами Довідкові таблиці
НФБК Кожен детермінант — потенційний ключ Аномалії від перекривних ключів Додаткові розбиття

Дані таблиці узагальнюють класичні визначення з теорії реляційних моделей (матеріали Вікіпедії та навчальні ресурси Microsoft Learn).

Після досягнення 3НФ більшість OLTP-систем вважаються достатньо нормалізованими. Подальші форми застосовують лише тоді, коли аналіз залежностей показує конкретні проблеми.

Поширені помилки, які руйнують навіть правильну схему

Багато розробників, особливо початківців, припускаються однакових помилок.

  • Зберігання списків у одному полі (телефон1, телефон2 або рядок із комами). Це пряме порушення 1НФ. Будь-який пошук за окремим номером стає неефективним і схильним до помилок.
  • Використання сурогатного ключа без аналізу природних залежностей. Сурогатний ідентифікатор зручний, але він не скасовує потребу перевіряти функціональні залежності між бізнес-атрибутами.
  • Надмірна нормалізація до 5НФ без реальної потреби. Кількість JOIN-ів зростає, запити сповільнюються, а виграш у цілісності стає невідчутним.
  • Ігнорування доменних обмежень. Навіть у 3НФ можна зберегти неправильні значення, якщо не задати CHECK-обмеження чи зовнішні ключі.
  • Копіювання структури з NoSQL-документів без адаптації. Документо-орієнтовані підходи дозволяють вкладеність, але в реляційній моделі це призводить до порушення атомарності.

Ці помилки не завжди проявляються одразу. Вони накопичуються і стають помітними під час масштабування або при зміні бізнес-правил.

Коли нормалізація шкодить і коли варто зупинитися

Повна нормалізація ідеально підходить для транзакційних систем з високою частотою змін. Однак у аналітичних сховищах і системах звітності велика кількість з’єднань може стати вузьким місцем.

Денормалізація — це свідоме введення контрольованої надмірності після досягнення нормальної форми. Її застосовують, коли вимірювання показують, що вартість JOIN перевищує вартість підтримки дубльованих даних. Типові прийоми 2026 року: матеріалізовані представлення, JSONB-стовпці для вкладених налаштувань користувача, окремі таблиці агрегатів для звітів.

За моїм досвідом використання цього підходу протягом місяця на проєкті з обсягом понад 50 мільйонів рядків, вибіркове денормалізування трьох найважчих запитів зменшило середній час відповіді з 1,8 с до 120 мс без втрати узгодженості основних транзакцій.

Рішення про денормалізацію має базуватися на вимірах, а не на припущеннях. Спочатку будують чисту 3НФ-схему, збирають статистику запитів, і лише потім вводять надмірність у точках, де вона дає найбільший ефект.

Міні-кейс: як одна неправильна залежність зупинила оновлення каталогу

У нашій практиці ми стикалися з таким випадком, коли інтернет-магазин електроніки не міг оновити ціни постачальника. Таблиця «Товари» містила поля: код_товару, назва, ціна, назва_постачальника, контакт_постачальника, рейтинг_постачальника. Рейтинг і контакт залежали від назви постачальника, а не від коду товару. При зміні рейтингу одного постачальника доводилося оновлювати сотні рядків. Частина оновлень пропускалася через блокування, і в системі з’являлися суперечливі значення.

Після декомпозиції з’явилися три таблиці: «Товари», «Постачальники» і «Ціни_постачальників». Оновлення рейтингу тепер торкалося лише одного рядка. Час масового оновлення цін скоротився з кількох годин до хвилин, а кількість інцидентів із розбіжністю даних впала до нуля протягом наступних шести місяців.

Цей приклад показує, що навіть невелика транзитивна залежність може паралізувати бізнес-процес.

Чек-лист самоперевірки схеми

Перед тим як вважати схему готовою, пройдіть цей список:

  1. Чи всі значення в клітинках атомарні?
  2. Чи існує первинний ключ у кожній таблиці?
  3. Чи немає неключових атрибутів, що залежать лише від частини складеного ключа?
  4. Чи немає транзитивних залежностей між неключовими атрибутами?
  5. Чи кожен зовнішній ключ посилається на існуючий первинний ключ?
  6. Чи перевірені основні запити на кількість JOIN і час виконання?
  7. Чи задокументовані всі функціональні залежності?

Якщо хоча б на одне питання відповідь негативна — схему варто переглянути.

Питання, які найчастіше ставлять розробники

До якого рівня нормалізації потрібно доходити в більшості проєктів?
Для транзакційних систем достатньо 3НФ або НФБК. Вищі форми застосовують лише за наявності доведених багатозначних залежностей.

Чи можна нормалізувати вже існуючу базу з даними?
Так, але процес потребує обережної міграції. Спочатку створюють нові таблиці, переносять дані скриптами з перевіркою цілісності, потім перемикають додаток і лише після цього видаляють старі структури.

Як нормалізація впливає на продуктивність у 2026 році?
Сучасні СУБД (PostgreSQL, SQL Server, MySQL) ефективно оптимізують JOIN завдяки індексам і статистиці. Проблеми виникають переважно при десяти й більше з’єднаннях у одному запиті або при відсутності правильних індексів.

Чи потрібна нормалізація в NoSQL-системах?
У документних і колоночних базах принципи інші. Там часто свідомо зберігають вкладені структури. Проте ідеї усунення неконтрольованої надмірності залишаються актуальними.

Що робити, якщо після нормалізації запити стали повільнішими?
Повернутися до вимірювань. Додати індекси, розглянути матеріалізовані представлення або вибіркову денормалізацію лише тих таблиць, які беруть участь у найповільніших запитах.

Нормалізація бази даних залишається одним із найнадійніших способів захистити дані від логічних суперечностей. Вона вимагає уваги до залежностей і готовності переглядати схему, коли бізнес-вимоги змінюються. Правильно побудована модель служить фундаментом, на якому можна безпечно додавати продуктивні оптимізації без втрати цілісності.

Денис Романенко

Денис Романенко

Київський IT-інженер. Почав з OS/2 у кінці 90-х, сидів на os2.kiev.ua, портував софт. Пізніше перейшов на Linux. Зараз DevOps/SRE: Kubernetes, безпека, VPN, автоматизація. Блог samm.kiev.ua веде з 2026-го — без хайпу, тільки те, що сам перевірив руками. Пише рідко, але по суті. Живе в Києві. Багато кави, мало сну, термінал майже завжди відкритий.

Leave a Reply

Your email address will not be published. Required fields are marked *