Ответ
Нормализация — это процесс организации структуры реляционной базы данных для минимизации избыточности данных и устранения аномалий при операциях вставки, обновления и удаления. В контексте Node.js приложений нормализация упрощает работу с данными через ORM и снижает вероятность рассогласования.
Проблема ненормализованной структуры (таблица user_orders):
-- Антипаттерн: все данные в одной таблице
CREATE TABLE user_orders (
order_id INT,
user_name VARCHAR(100),
user_email VARCHAR(100),
user_phone VARCHAR(20),
product_name VARCHAR(100),
product_price DECIMAL(10,2),
product_category VARCHAR(50),
order_date DATE
);
-- Проблемы:
-- 1. Избыточность: данные пользователя дублируются в каждом заказе
-- 2. Аномалия обновления: изменение email требует обновления всех записей
-- 3. Аномалия удаления: удаление заказа может удалить информацию о продукте
Нормализация до 3NF:
-- 1NF: Атомарные значения, нет повторяющихся групп
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
phone VARCHAR(20)
);
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
category_id INT REFERENCES categories(category_id)
);
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(user_id),
order_date DATE DEFAULT CURRENT_DATE,
status VARCHAR(20) DEFAULT 'pending'
);
CREATE TABLE order_items (
order_item_id SERIAL PRIMARY KEY,
order_id INT REFERENCES orders(order_id),
product_id INT REFERENCES products(product_id),
quantity INT NOT NULL CHECK (quantity > 0),
price_at_time DECIMAL(10,2) NOT NULL -- Историческая цена
);
CREATE TABLE categories (
category_id SERIAL PRIMARY KEY,
name VARCHAR(50) UNIQUE NOT NULL
);
Реализация в Node.js с Sequelize:
// Модель User
const User = sequelize.define('User', {
name: { type: DataTypes.STRING, allowNull: false },
email: { type: DataTypes.STRING, unique: true, allowNull: false }
});
// Модель Product
const Product = sequelize.define('Product', {
name: { type: DataTypes.STRING, allowNull: false },
price: { type: DataTypes.DECIMAL(10,2), allowNull: false }
});
// Модель Order с ассоциациями
const Order = sequelize.define('Order', {
status: { type: DataTypes.STRING, defaultValue: 'pending' }
});
// Определение связей
User.hasMany(Order, { foreignKey: 'userId' });
Order.belongsTo(User, { foreignKey: 'userId' });
Order.belongsToMany(Product, { through: 'OrderItem' });
Product.belongsToMany(Order, { through: 'OrderItem' });
// Использование нормализованной структуры
const userWithOrders = await User.findOne({
where: { email: 'john@example.com' },
include: [{
model: Order,
include: [Product]
}]
});
Преимущества нормализации для Node.js приложений:
-
Снижение избыточности данных:
// Вместо хранения всей информации о пользователе в каждом заказе // храним только user_id и JOIN'им при необходимости -
Устранение аномалий:
- Вставки: Можно добавить продукт без заказа
- Обновления: Email пользователя обновляется в одном месте
- Удаления: Удаление заказа не удаляет информацию о продукте
-
Улучшение производительности запросов:
-- Индексы работают эффективнее на нормализованных таблицах CREATE INDEX idx_orders_user_id ON orders(user_id); CREATE INDEX idx_products_category ON products(category_id); -
Гибкость схемы: Легче добавлять новые типы данных и отношения
Когда денормализация оправдана:
- Частые сложные JOIN'ы, влияющие на производительность
- Таблицы для отчетности или аналитики (OLAP)
- Кэширование часто запрашиваемых агрегированных данных
- Системы с преимущественно операциями чтения
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶