Stage 1. Реляционные базы данных и реляционная модель
Реляционная база данных — это база, которая хранит структурированные данные в таблицах и позволяет связывать записи, относящиеся друг к другу. Модель называется реляционной, потому что данные не складываются в один огромный объект или один длинный файл. Вместо этого связанные факты разделяются по таблицам, а отношения между строками выражаются через ключи.
Реляционная модель — это способ организовать данные так, чтобы база оставалась понятной и надежной даже при росте проекта. В таблице есть столбцы, которые описывают хранимые поля, и строки, которые содержат конкретные записи. Главная польза модели: вы заранее задаете структуру, связи и ограничения, а база помогает не допускать хаос в данных.

Базовые термины без перегруза
| Термин | Что это значит на практике | Пример |
|---|---|---|
| Таблица | Набор однотипных объектов | users, orders |
| Столбец | Поле объекта с типом данных | email, created_at |
| Строка | Один конкретный объект | Один заказ |
| Primary key | Уникальный идентификатор строки | orders.id |
| Foreign key | Ссылка на строку другой таблицы | orders.user_id -> users.id |
| RDBMS/СУБД | Программа, которая управляет реляционной базой | PostgreSQL, MySQL, Oracle Database |
| Ограничение | Правило, которое проверяет сама база | NOT NULL, UNIQUE |
Ключевая идея: одна таблица должна хранить один тип сущности. Пользователь — в users, заказ — в orders, оплата — в payments. Если дублировать данные пользователя в каждой строке заказа, рано или поздно возникнут расхождения.
RDBMS, или реляционная система управления базами данных, — это программный слой, который хранит таблицы, проверяет правила, выполняет SQL-запросы, управляет доступом и делает данные устойчивыми к сбоям. Когда разработчики говорят “мы используем PostgreSQL” или “приложение пишет в MySQL”, обычно имеется в виду, что приложение обращается к СУБД, а СУБД управляет реальными файлами и операциями реляционной базы.
Почему таблицы разделяют, а не дублируют
Представьте небольшой магазин с клиентами и заказами. Простое, но слабое решение — хранить имя клиента, телефон, адрес и все детали заказа в одной большой таблице orders. Сначала это кажется удобным, но быстро появляются проблемы. Если клиент меняет адрес, нужно обновить много строк. Если одну строку забыли, в базе уже есть несколько противоречащих версий одного клиента.
Реляционный подход хранит данные клиента один раз в users, а данные заказа — в orders. Колонка orders.user_id указывает на нужную строку в users. Общий ключ позволяет приложению найти адрес доставки клиента при обработке заказа без копирования этих данных в каждую строку заказа. На этой идее строятся следующие темы: joins, нормализация и ограничения внешних ключей.
Простая схема для старта
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
amount NUMERIC(10,2) NOT NULL,
status TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
Что обеспечивается этой схемой:
PRIMARY KEYгарантирует уникальность строки;FOREIGN KEYзапрещает заказ без существующего пользователя;NOT NULLзащищает обязательные поля;UNIQUEне даст два одинаковых email.
Эти гарантии — примеры целостности данных. Целостность означает, что база не просто хранит байты, а применяет правила, которые сохраняют смысл данных. Таблица может отклонить пустое обязательное значение, повторяющийся идентификатор, ссылку на несуществующую строку или значение неправильного типа. Это важно, потому что в реальных системах данные часто записывает не только основной код приложения. Импорты, админки, фоновые задачи и несколько сервисов могут работать с одной базой. Правила на уровне базы защищают данные даже тогда, когда у одного из клиентов есть ошибка.
Логическая модель и физическое хранение
Реляционная база отделяет логическую структуру от физического хранения. Логическая структура — это то, с чем работает разработчик: таблицы, колонки, представления, индексы, ключи и ограничения. Физическое хранение — это то, как СУБД размещает данные на диске или в памяти, делит файлы, кэширует страницы и эффективно ищет строки.
Это разделение важно. Разработчик может написать SELECT * FROM orders и не знать, в каком файле лежат строки и сколько страниц диска прочитает СУБД. Администратор базы может переносить файлы, настраивать хранение, добавлять индексы или менять внутреннюю организацию данных без переименования таблицы orders в приложении. SQL описывает, какие данные нужны; СУБД решает, как к ним обратиться.
Пошаговый разбор запроса (строка за строкой)
SELECT id, user_id, amount, status, created_at
FROM orders
WHERE status = 'PAID'
ORDER BY created_at DESC
LIMIT 5;
Разбираем каждую строку:
SELECT id, user_id, amount, status, created_at: Какие колонки вернуть в ответ. Здесь мы явно выбираем только нужные поля, а не*.FROM orders: Из какой таблицы брать данные. Источник выборки — таблица заказов.WHERE status = 'PAID': Условие фильтрации. В результат попадут только оплаченные заказы.ORDER BY created_at DESC: Сортировка результата.DESCозначает от новых к старым.LIMIT 5: Ограничение количества строк. Возьмем только 5 записей после фильтра и сортировки.
Итоговый смысл всего запроса: “Покажи 5 последних оплаченных заказов”.
SQL, транзакции и согласованность
SQL — стандартный язык для определения, чтения и изменения данных в реляционных базах. CREATE TABLE задает структуру, INSERT добавляет строки, SELECT читает строки, а в следующих уроках появятся UPDATE, DELETE, joins, группировка, индексы и транзакции. SQL декларативен: обычно вы описываете нужный результат, а СУБД строит план выполнения.
Реляционные базы часто выбирают там, где особенно важна корректность. Например, если банковское пополнение сохранено, обновленный баланс должен быть виден согласованно. Если интернет-магазин резервирует несколько товаров, которые должны уйти вместе, то должны зафиксироваться все изменения остатков или ни одно из них. Такое поведение “все или ничего” называется атомарностью.
Атомарность входит в ACID — набор свойств транзакций, с которыми обычно ассоциируют реляционные базы:
| Свойство | Практический смысл |
|---|---|
| Atomicity / атомарность | Транзакция выполняется полностью или не применяется вообще |
| Consistency / согласованность | Данные остаются валидными по правилам базы |
| Isolation / изоляция | Незавершенные изменения не должны сбивать другие параллельные операции |
| Durability / долговечность | Зафиксированные изменения переживают сбои, например перезапуск |
На первом уроке не нужно подробно разбираться с транзакциями, но важно понять: реляционная модель — это не только таблицы. Она также дает базе способ поддерживать точность данных по правилам, пока с ними одновременно работают многие пользователи и программы.
Параллельный доступ и блокировки
Реальные базы используются совместно. Несколько пользователей, API-запросов, фоновых обработчиков и отчетов могут читать или менять данные одновременно. Конкурентность — это способность базы обслуживать такую параллельную активность и при этом сохранять корректность.
Когда две операции пытаются изменить одну и ту же строку, СУБД может использовать блокировки или версионность, чтобы итоговое состояние осталось валидным. Блокировка временно защищает данные, которые сейчас изменяются. Хорошие реляционные базы стараются блокировать только необходимое, часто одну строку, а не всю таблицу, потому что широкие блокировки ухудшают производительность. Уровни изоляции будут отдельной темой позже, но базовая идея простая: база должна сочетать скорость с безопасным доступом к общим данным.
Что важно понять до следующей темы
Реляционная модель — это не сложная теория, а практический каркас для хранения связанных фактов с понятными правилами. Если таблицы разделены по сущностям, ключи заданы, связи корректны, а ограничения защищают важные поля, то SQL-запросы становятся предсказуемыми и намного проще для поддержки.
При выборе или использовании СУБД команды обычно смотрят на точность данных, масштабируемость, конкурентность, производительность, надежность и удобство эксплуатации. У разных продуктов разные сильные стороны, но базовые реляционные идеи остаются общими: таблицы представляют структурированные факты, ключи связывают эти факты, ограничения защищают их, а SQL дает приложениям общий способ с ними работать.
Практика перед следующим уроком
Скопируйте команды ниже и выполните их по шагам.
Шаг 1. Добавьте пользователей:
INSERT INTO users(name, email) VALUES
('Anna', '[email protected]'),
('Ivan', '[email protected]'),
('Olga', '[email protected]');
Шаг 2. Добавьте заказы:
INSERT INTO orders(user_id, amount, status, created_at) VALUES
(1, 1200.00, 'PAID', '2026-05-10 12:00:00'),
(1, 300.00, 'NEW', '2026-05-10 11:00:00'),
(2, 700.00, 'PAID', '2026-05-10 10:00:00'),
(3, 450.00, 'CANCELLED', '2026-05-10 09:00:00'),
(2, 900.00, 'PAID', '2026-05-10 08:00:00'),
(1, 150.00, 'PAID', '2026-05-10 07:00:00'),
(3, 510.00, 'NEW', '2026-05-10 06:00:00'),
(2, 810.00, 'PAID', '2026-05-10 05:00:00');
Шаг 3. Запустите запрос:
SELECT id, user_id, amount, status, created_at
FROM orders
WHERE status = 'PAID'
ORDER BY created_at DESC
LIMIT 5;
Шаг 4. Сверьте результат:
- должны остаться только строки со статусом
PAID; - первая строка должна быть самой новой по
created_at; - строк должно быть не больше 5.
Если у вас вышло иначе, значит ошибка в одном из блоков: WHERE, ORDER BY или LIMIT.