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

«Что такое нормализация базы данных?» — вопрос из категории Базы данных, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Основные нормальные формы:

  1. 1NF (Первая нормальная форма): Устранить повторяющиеся группы. Все значения в столбцах атомарны (неделимы), каждая запись уникальна.
  2. 2NF (Вторая нормальная форма): Должна выполняться 1NF. Устранить частичные зависимости — все неключевые атрибуты должны полностью зависеть от всего первичного ключа (а не от его части).
  3. 3NF (Третья нормальная форма): Должна выполняться 2NF. Устранить транзитивные зависимости — неключевые атрибуты не должны зависеть от других неключевых атрибутов.

Пример на Node.js с PostgreSQL:

-- Денормализованная таблица (проблемы: дублирование, аномалии обновления)
CREATE TABLE denormalized_orders (
  order_id INT,
  customer_name VARCHAR,
  customer_email VARCHAR,
  product_name VARCHAR,
  product_price DECIMAL
);

-- Нормализованная схема (3NF)
CREATE TABLE customers (
  customer_id SERIAL PRIMARY KEY,
  name VARCHAR NOT NULL,
  email VARCHAR UNIQUE NOT NULL
);

CREATE TABLE products (
  product_id SERIAL PRIMARY KEY,
  name VARCHAR NOT NULL,
  price DECIMAL NOT NULL
);

CREATE TABLE orders (
  order_id SERIAL PRIMARY KEY,
  customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADE,
  order_date TIMESTAMP DEFAULT NOW()
);

CREATE TABLE order_items (
  order_id INT REFERENCES orders(order_id) ON DELETE CASCADE,
  product_id INT REFERENCES products(product_id),
  quantity INT NOT NULL,
  PRIMARY KEY (order_id, product_id)
);

Практическое применение в Node.js: При работе с ORM, например, Sequelize, нормализация отражается в моделях и связях:

// Модели Sequelize, соответствующие нормализованной схеме
const Customer = sequelize.define('Customer', { name: DataTypes.STRING, email: DataTypes.STRING });
const Product = sequelize.define('Product', { name: DataTypes.STRING, price: DataTypes.DECIMAL });
const Order = sequelize.define('Order', { date: DataTypes.DATE });
const OrderItem = sequelize.define('OrderItem', { quantity: DataTypes.INTEGER });

// Определение связей
Customer.hasMany(Order);
Order.belongsTo(Customer);
Order.belongsToMany(Product, { through: OrderItem });
Product.belongsToMany(Order, { through: OrderItem });

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