Ответ
Нормализация — это процесс проектирования структуры реляционной базы данных, направленный на устранение избыточности данных и аномалий при операциях вставки, обновления и удаления (INSERT, UPDATE, DELETE). Она достигается путем декомпозиции таблиц и приведения их к нормальным формам.
Основные нормальные формы, которые я применяю на практике:
-
Первая нормальная форма (1NF): Устраняет повторяющиеся группы. Каждое поле содержит атомарные (неделимые) значения, а в таблице нет массивов или списков в одной ячейке.
- До:
Orders(order_id, products: "Книга,Ручка,Блокнот") - После: Отдельная таблица
Order_Items(order_id, product_name).
- До:
-
Вторая нормальная форма (2NF): Должна выполняться 1NF, и все неключевые атрибуты должны полностью зависеть от всего составного первичного ключа, а не от его части.
- Проблема: В таблице
Order_Items(order_id, product_id, product_name, quantity)полеproduct_nameзависит только отproduct_id, а не от пары(order_id, product_id). - Решение: Вынести
product_nameв отдельную таблицуProducts(product_id, product_name).
- Проблема: В таблице
-
Третья нормальная форма (3NF): Должна выполняться 2NF, и не должно быть транзитивных зависимостей (когда неключевой атрибут зависит от другого неключевого атрибута).
- Проблема: В таблице
Orders(order_id, customer_id, customer_phone)полеcustomer_phoneзависит отcustomer_id, а не напрямую отorder_id. - Решение: Вынести
customer_phoneв таблицуCustomers(customer_id, customer_phone).
- Проблема: В таблице
Пример нормализованной схемы для заказов:
-- Основные сущности
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100) UNIQUE
);
CREATE TABLE products (
product_id INT PRIMARY KEY,
name VARCHAR(100),
price DECIMAL(10,2)
);
-- Связующие таблицы
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
CREATE TABLE order_items (
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)
);
Преимущества нормализации: целостность данных, эффективное использование памяти, упрощение операций обновления. Недостаток: более сложные запросы с большим количеством JOIN, что иногда требует денормализации для оптимизации чтения в высоконагруженных системах.
Ответ 18+ 🔞
Давай разберем эту тему без соплей, а то некоторые думают, что нормализация — это когда ты просто таблицы на кучки разложил. Нет, блядь, это целая наука, чтобы твоя база не превратилась в сраное месиво, где одно изменение влечёт за собой овердохуища проблем.
Если по-простому, то нормализация — это когда ты наводишь порядок в своих таблицах, чтобы данные не дублировались как у дурака, и чтобы когда ты что-то обновлял, удалял или вставлял, у тебя всё не ебнулось к чертям. Аномалии эти самые — они как хитрая жопа: вроде всё работает, а потом раз — и пиздец.
Вот как я это обычно делаю, на пальцах:
-
Первая нормальная форма (1NF): Это базовый уровень, ёпта. Ты должен избавиться от всякой хуйни вроде списков через запятую в одной ячейке. Каждое значение — атомарное, то есть неделимое. Представь, что у тебя в поле
productsзаписано"Молоток,Гвозди,Доска". Это пиздец, а не поле. Как ты потом искать будешь? Что обновлять?- Было:
Заказы(id_заказа, товары: "Молоток,Гвозди,Доска")— манда с ушами. - Стало: Отдельная таблица
ПозицииЗаказа(id_заказа, название_товара). Всё, теперь каждый товар — отдельная запись. Порядок.
- Было:
-
Вторая нормальная форма (2NF): Тут уже интереснее. Чтоб её достичь, нужна первая. Суть в том, что если у тебя ключ составной (из нескольких полей), то все остальные поля должны зависеть от ВСЕГО этого ключа, а не от его кусочка. Иначе будет пиздопроебибна.
- Проблема: Допустим, таблица
ПозицииЗаказа(id_заказа, id_товара, название_товара, количество). Ключ у нас(id_заказа, id_товара). Но поленазвание_товаразависит только отid_товара! Получается, если один и тот же товар в 100 заказах, его название будет повторяться 100 раз. Обновил название в одном месте — и сиди, обновляй в остальных 99. Доверия к такой схеме — ноль ебать. - Решение: Выносим
название_товарав отдельную таблицуТовары(id_товара, название_товара). Теперь всё чисто.
- Проблема: Допустим, таблица
-
Третья нормальная форма (3NF): Это когда уже и вторая есть. Тут ловим транзитивные зависимости. Звучит страшно, а на деле: неключевое поле не должно зависеть от другого неключевого поля. Оно должно зависеть ТОЛЬКО от первичного ключа.
- Проблема: Таблица
Заказы(id_заказа, id_клиента, телефон_клиента). Ключ —id_заказа. Полетелефон_клиентазависит не от ключа, а отid_клиента. Опять дублирование: один клиент сделал 50 заказов — его телефон записан 50 раз. Клиент сменил номер — волнение ебать, надо бегать по всем заказам. - Решение: Выносим
телефон_клиента(и вообще все данные клиента) в таблицуКлиенты(id_клиента, телефон_клиента). Теперь логично, да?
- Проблема: Таблица
Вот смотри, как выглядит нормальная схема после всех этих телодвижений:
-- Основные сущности (клиенты и товары — отдельно, как и положено)
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100) UNIQUE
);
CREATE TABLE products (
product_id INT PRIMARY KEY,
name VARCHAR(100),
price DECIMAL(10,2)
);
-- Заказы — это одна сущность
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
-- А что внутри заказа — это связующая таблица. Классика!
CREATE TABLE order_items (
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)
);
Что в итоге? Преимущества — да, ёбать колотить, целостность данных, обновлять что-то в одном месте — красота, место экономится. Но есть и подстава: чтобы получить полную информацию о заказе, тебе теперь надо сделать JOIN аж по трём таблицам. На маленьких объёмах — похуй, а когда данных овердохуища, запросы могут тормозить. Поэтому для чисто аналитических или высоконагруженных на чтение систем иногда идут на денормализацию — сознательно допускают дублирование, чтобы меньше джойнить. Но это уже осознанный грех, а не беспорядок по незнанию. Сначала научись нормализовать, а потом уже решай, где можно нахулиганить.
Видео-ответы
▶
▶
▶
▶
▶
▶