Иерархические данные в реляционных БД
Категории товаров, оргструктура, меню, комментарии с ответами — деревья встречаются в каждом продукте. Реляционная модель — таблицы и строки; дерево нужно смоделировать.
База: SQL — язык, JOIN и объединения, рекурсивные CTE.
Три распространённые модели
| Модель | Идея | Чтение поддерева | Вставка узла | Сложность |
|---|---|---|---|---|
Adjacency list (parent_id) | Ссылка на родителя | Рекурсивный CTE | O(1) | Низкая |
Nested sets (left, right) | Интервалы обхода | Один диапазон | O(n) сдвигов | Средняя |
| Closure table | Все пары предок–потомок | JOIN по ancestor | O(depth) строк | Выше объём |
Adjacency list (parent_id)
CREATE TABLE category (
id BIGINT PRIMARY KEY,
parent_id BIGINT REFERENCES category(id),
name TEXT NOT NULL
);
Плюсы: просто объяснить, дешёвые вставки и перенос ветки (обновить parent_id).
Минусы: «все потомки узла 42» — рекурсия. В PostgreSQL, SQL Server, Oracle — рекурсивный CTE:
WITH RECURSIVE tree AS (
SELECT id, parent_id, name, 1 AS depth
FROM category WHERE id = 42
UNION ALL
SELECT c.id, c.parent_id, c.name, t.depth + 1
FROM category c
JOIN tree t ON c.parent_id = t.id
)
SELECT * FROM tree;
Для глубоких деревьев (тысячи уровней — редкость) следите за индексом (parent_id).
Nested sets
Каждый узел получает номера left и right обхода «в глубину». Потомки узла — все строки, у которых left и right лежат внутри интервала родителя.
Плюсы: выборка поддерева без рекурсии — один WHERE left BETWEEN ….
Минусы: вставка/удаление сдвигает границы у многих строк — плохо при частых изменениях и высокой конкуренции.
Подходит для реже меняющихся каталогов (справочники, таксономии).
Closure table
Отдельная таблица (ancestor_id, descendant_id, depth) со всеми парами на пути.
Плюсы: быстрые запросы «все предки», «все потомки», гибкая глубина.
Минусы: больше строк при вставке; нужна дисциплина поддержания при переносе ветки.
Хорошо для частых сложных запросов по иерархии при умеренной частоте записи.
Материализованный путь (дополнение)
Колонка path вида /1/5/12/ — быстрый LIKE '/1/5/%', но перенос узла требует обновления всех потомков. Иногда комбинируют с parent_id.
Когда что выбирать
| Сценарий | Рекомендация |
|---|---|
| Типичный CRUD, глубина < 10 | parent_id + CTE |
| Частое чтение дерева целиком, редкие правки | Nested sets |
| Сложная аналитика по предкам/потомкам | Closure table |
| Граф «друзья друзей», не дерево | Таблица рёбер + графовая БД |
Ограничения целостности
FOREIGN KEYнаparent_id— не удалить родителя с детьми без CASCADE или переноса.- Запрет циклов: триггер или проверка при переносе (в closure — проще валидировать).
- Для nested sets — транзакция на всю операцию сдвига.
Связанные темы
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Вот SQL как раз обеспечивает такую связь и это главное отличие реляционных БД - реляции (relations), что означает связи. Знакомимся с языком - ставим программы, запускаем, выполняем первые запросы. От файлового хранения к реляционной и современной мультимодельной СУБД — термины, причины появления SQL и базовая классификация систем. Домены, атрибуты, кортежи и отношения — свойства реляционных таблиц и ограничения целостности при проектировании схемы. Функциональные зависимости, нормальные формы 1НФ–3НФ, аномалии обновления и осознанная денормализация при проектировании схемы. Метаданные СУБД через information_schema и pg_catalog — запросы к структуре таблиц, ключей и индексов в PostgreSQL. Логическое и физическое резервное копирование, pg_dump, pg_restore, WAL и восстановление на точку во времени (PITR). Логический порядок выполнения SELECT, проекция, WHERE, DISTINCT, ORDER BY и правила читаемого форматирования запросов. Скалярные и коррелированные подзапросы, EXISTS против IN, особенности NULL и выбор между подзапросом и JOIN. AND, OR, NOT, приоритет операторов, NULL и UNKNOWN, IS NULL, NOT IN и IS DISTINCT FROM в PostgreSQL. MVCC, уровни блокировок таблиц, FOR UPDATE, SKIP LOCKED, взаимоблокировки и диагностика через pg_locks. Учебная схема интернет-магазина для PostgreSQL — DDL и примеры запросов по темам курса SQL.SQL - язык структурированных запросов
Первые шаги с SQL
Эволюция систем хранения данных
Реляционная модель данных
Нормализация данных
Словарь данных и системные каталоги
Резервное копирование и восстановление PostgreSQL
Оператор SELECT — синтаксис и стиль
Подзапросы, EXISTS и IN
Фильтрация и трёхзначная логика
Блокировки и конкурентный доступ в PostgreSQL
Практикум shop_data