Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Пример нормализованных данных
Нормализация данных - это процесс организации данных в базе данных для снижения избыточности и улучшения целостности. Рассмотрим примеры от ненормализованного к нормализованному виду.
Пример 1: Неправильная структура (денормализованная)
# Плохо: данные дублируются
students = [
{
"id": 1,
"name": "Alice",
"email": "alice@example.com",
"course": "Python",
"course_code": "PY101",
"instructor": "John",
"instructor_email": "john@example.com",
"instructor_phone": "+1-555-1234"
},
{
"id": 2,
"name": "Bob",
"email": "bob@example.com",
"course": "Python",
"course_code": "PY101",
"instructor": "John",
"instructor_email": "john@example.com",
"instructor_phone": "+1-555-1234"
}
]
Проблемы:
- Данные об инструкторе повторяются в каждом студенте
- Если изменить email инструктора, придётся обновлять много записей
- Много дублирования данных
Пример 2: Нормализованная структура (1НФ, 2НФ, 3НФ)
# Таблица Instructors
instructors = [
{
"instructor_id": 1,
"name": "John",
"email": "john@example.com",
"phone": "+1-555-1234"
}
]
# Таблица Courses
courses = [
{
"course_id": 1,
"name": "Python",
"code": "PY101",
"instructor_id": 1
}
]
# Таблица Students
students = [
{
"student_id": 1,
"name": "Alice",
"email": "alice@example.com",
"course_id": 1
},
{
"student_id": 2,
"name": "Bob",
"email": "bob@example.com",
"course_id": 1
}
]
# Таблица Enrollments (связь many-to-many)
enrollments = [
{"enrollment_id": 1, "student_id": 1, "course_id": 1},
{"enrollment_id": 2, "student_id": 2, "course_id": 1}
]
Преимущества:
- Нет дублирования данных
- Один инструктор - одна запись
- Легко обновить email инструктора в одном месте
- Легко добавлять новых студентов
Пример 3: SQL для нормализованной структуры
CREATE TABLE instructors (
instructor_id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100),
phone VARCHAR(20)
);
CREATE TABLE courses (
course_id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
code VARCHAR(10) UNIQUE,
instructor_id INT,
FOREIGN KEY (instructor_id) REFERENCES instructors(instructor_id)
);
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100)
);
CREATE TABLE enrollments (
enrollment_id INT PRIMARY KEY,
student_id INT,
course_id INT,
FOREIGN KEY (student_id) REFERENCES students(student_id),
FOREIGN KEY (course_id) REFERENCES courses(course_id)
);
Пример 4: Python ORM с нормализованной структурой
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
class Instructor(Base):
__tablename__ = "instructors"
instructor_id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
email = Column(String(100))
phone = Column(String(20))
courses = relationship("Course", back_populates="instructor")
class Course(Base):
__tablename__ = "courses"
course_id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
code = Column(String(10), unique=True)
instructor_id = Column(Integer, ForeignKey("instructors.instructor_id"))
instructor = relationship("Instructor", back_populates="courses")
enrollments = relationship("Enrollment", back_populates="course")
class Student(Base):
__tablename__ = "students"
student_id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
email = Column(String(100))
enrollments = relationship("Enrollment", back_populates="student")
class Enrollment(Base):
__tablename__ = "enrollments"
enrollment_id = Column(Integer, primary_key=True)
student_id = Column(Integer, ForeignKey("students.student_id"))
course_id = Column(Integer, ForeignKey("courses.course_id"))
student = relationship("Student", back_populates="enrollments")
course = relationship("Course", back_populates="enrollments")
Пример 5: Запрос нормализованных данных
# Получить всех студентов, записанных на курс "Python"
from sqlalchemy import select
query = select(Student).join(Enrollment).join(Course).filter(
Course.name == "Python"
)
students = session.execute(query).scalars().all()
# Результат
for student in students:
print(f"{student.name} - {student.email}")
# Получить курсы конкретного инструктора
query = select(Course).filter(
Course.instructor.has(Instructor.name == "John")
)
courses = session.execute(query).scalars().all()
Уровни нормализации
1НФ (First Normal Form):
- Атомарные значения в каждой ячейке (не массивы, не объекты)
- Нет повторяющихся групп
# Плохо (2НФ нарушена)
student = {
"id": 1,
"name": "Alice",
"courses": ["Python", "JavaScript"] # Массив
}
# Хорошо (1НФ)
student = {"id": 1, "name": "Alice"}
courses = [
{"course_id": 1, "student_id": 1, "name": "Python"},
{"course_id": 2, "student_id": 1, "name": "JavaScript"}
]
2НФ (Second Normal Form):
- Выполнена 1НФ
- Все неключевые атрибуты полностью функционально зависят от первичного ключа
# Плохо
course = {
"course_id": 1,
"name": "Python",
"instructor_name": "John",
"instructor_email": "john@example.com"
}
# Хорошо
course = {
"course_id": 1,
"name": "Python",
"instructor_id": 1
}
instructor = {
"instructor_id": 1,
"name": "John",
"email": "john@example.com"
}
3НФ (Third Normal Form):
- Выполнена 2НФ
- Нет транзитивных зависимостей
# Плохо
student = {
"id": 1,
"name": "Alice",
"course_id": 1,
"course_name": "Python",
"instructor_name": "John"
}
# Хорошо (отдельные таблицы для каждой сущности)
student = {"id": 1, "name": "Alice", "course_id": 1}
course = {"course_id": 1, "name": "Python", "instructor_id": 1}
instructor = {"instructor_id": 1, "name": "John"}
Практический пример из жизни
# Денормализованная схема (неправильно)
users_orders = [
{
"order_id": 1,
"user_id": 1,
"user_name": "Alice",
"user_email": "alice@example.com",
"product_id": 101,
"product_name": "Laptop",
"product_price": 999,
"quantity": 1,
"total": 999
},
{
"order_id": 2,
"user_id": 1,
"user_name": "Alice", # Дублирование
"user_email": "alice@example.com", # Дублирование
"product_id": 102,
"product_name": "Mouse",
"product_price": 25,
"quantity": 2,
"total": 50
}
]
# Нормализованная схема (правильно)
users = [
{"user_id": 1, "name": "Alice", "email": "alice@example.com"}
]
products = [
{"product_id": 101, "name": "Laptop", "price": 999},
{"product_id": 102, "name": "Mouse", "price": 25}
]
orders = [
{"order_id": 1, "user_id": 1}
]
order_items = [
{"order_item_id": 1, "order_id": 1, "product_id": 101, "quantity": 1},
{"order_item_id": 2, "order_id": 2, "product_id": 102, "quantity": 2}
]
Итоговые выводы
- Нормализация удаляет дублирование данных
- Облегчает обновление и поддержку данных
- Повышает целостность данных
- Требует больше JOIN операций при запросах
- Есть баланс между нормализацией и производительностью
- Иногда денормализация нужна для оптимизации скорости