Как должны храниться данные в третьей форме?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как должны храниться данные в третьей нормальной форме (3NF)
Третья нормальная форма (3NF) — это состояние базы данных, при котором исключены все аномалии обновлений и удаления, а также обеспечена целостность данных через правильное разделение таблиц и использование внешних ключей.
Предпосылки для 3NF
Прежде чем достичь третьей нормальной формы, база должна удовлетворять:
- Первая нормальная форма (1NF) — атомарные значения (нет массивов/вложенных таблиц)
- Вторая нормальная форма (2NF) — нет частичной зависимости от составного ключа
Правило третьей нормальной формы
Третья нормальная форма требует:
- Каждый неключевой атрибут зависит только от первичного ключа
- Нет транзитивных зависимостей (когда неключевой атрибут зависит от другого неключевого атрибута)
Правильно: Атрибут -> Первичный ключ
Неправильно: Атрибут -> Другой атрибут -> Первичный ключ
Пример нарушения 3NF
Плохо (не соответствует 3NF)
Таблица студентов с информацией о факультете:
студенты
├── student_id (первичный ключ)
├── name
├── department_id
├── department_name (Зависит от department_id, не от student_id!)
└── department_head
Проблемы:
- Дублирование данных — одно и то же имя факультета повторяется для каждого студента
- Аномалия обновления — если изменить название факультета, нужно обновить все строки студентов
- Аномалия удаления — если удалить всех студентов факультета, потеряем информацию о факультете
Хорошо (соответствует 3NF)
Отдельные таблицы:
студенты факультеты
├── student_id ├── department_id
├── name ├── name
└── department_id -------> ├── head
└── ...
Практический пример: интернет-магазин
Денормализованная структура (плохо)
// Одна таблица со всем
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_name VARCHAR(100),
customer_email VARCHAR(100),
customer_phone VARCHAR(20),
customer_city VARCHAR(100),
product_id INT,
product_name VARCHAR(100),
product_price DECIMAL(10,2),
product_category VARCHAR(100),
quantity INT,
order_date TIMESTAMP
);
Проблемы:
- Информация о клиенте повторяется в каждом заказе
- Информация о товаре повторяется для каждого заказа
- Если изменить цену товара, нужно обновить все заказы
Нормализованная структура (хорошо, 3NF)
// Таблица клиентов
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE,
phone VARCHAR(20),
city VARCHAR(100)
);
// Таблица товаров
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
category_id INT,
FOREIGN KEY (category_id) REFERENCES categories(category_id)
);
// Таблица категорий
CREATE TABLE categories (
category_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
// Таблица заказов
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT NOT NULL,
order_date TIMESTAMP DEFAULT NOW(),
total_amount DECIMAL(10,2),
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
// Таблица позиций заказа (связь)
CREATE TABLE order_items (
order_item_id SERIAL PRIMARY KEY,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
price_at_purchase DECIMAL(10,2) NOT NULL,
FOREIGN KEY (order_id) REFERENCES orders(order_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
Преимущества:
- Нет дублирования — информация хранится в одном месте
- Легко обновлять — изменения обновляют только одну таблицу
- Целостность — внешние ключи гарантируют корректность данных
Ключевые принципы 3NF
1. Первичные ключи
Каждая таблица должна иметь уникальный первичный ключ:
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
email VARCHAR(100) UNIQUE,
name VARCHAR(100)
);
2. Внешние ключи
Для связей между таблицами используются внешние ключи:
CREATE TABLE posts (
post_id SERIAL PRIMARY KEY,
user_id INT NOT NULL,
title VARCHAR(255),
content TEXT,
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
3. Минимизация дублирования
// Плохо: одинаковые данные в разных таблицах
users (user_id, email, city_name, city_zip_code)
cities (city_id, city_name, city_zip_code) // дублирование!
// Хорошо: ссылка на единый источник
users (user_id, email, city_id)
cities (city_id, name, zip_code)
4. Избегание транзитивных зависимостей
// Плохо: author_country зависит от author, не от book
books (
book_id,
title,
author_id,
author_name,
author_country // транзитивная зависимость!
)
// Хорошо: разные таблицы
books (book_id, title, author_id)
authors (author_id, name, country)
Когда денормализовать?
Хотя 3NF — это идеальная цель, иногда стратегическая денормализация допустима:
// Приемлемо: кэширование часто используемых данных
CREATE TABLE order_summaries (
order_id INT PRIMARY KEY,
customer_name VARCHAR(100), // кэш для быстрого доступа
total_amount DECIMAL(10,2),
FOREIGN KEY (order_id) REFERENCES orders(order_id)
);
Причины для денормализации:
- Производительность — уменьшение количества JOIN'ов
- Часто читаемые данные — быстрее доступ
Но это должно быть осознанным выбором, не забывая синхронизировать кэшированные данные.
Итоги
В третьей нормальной форме:
- Каждый неключевой атрибут зависит только от первичного ключа
- Нет транзитивных зависимостей между неключевыми атрибутами
- Данные распределены по связанным таблицам
- Внешние ключи обеспечивают целостность
- Минимум дублирования и аномалий обновления
3NF — это стандарт для production баз данных и обеспечивает целостность, масштабируемость и легкость поддержания.