Как стать автором
Обновить

Комментарии 29

Автор проспал первые два курса вуза? А, просто неуч.

Я как-то не понял, почему потребовалось придумывать какой-то "идентификатор всего дерева" (который, кстати, ещё надо как-то задавать - этот момент стыдливо опущен... а зря) вместо совершенно очевидного решения использовать в качестве атрибута принадлежности дереву идентификатор корневого узла. При таком решении части преодолеваемых далее по тексту проблем просто не существует...

К слову, наличие такого идентификатора никак не решает задачу "как получить все дерево из базы" - вы можете получить только (несортированный) список всех узлов дерева, который сам по себе деревом, увы, не является.

Ну и вместо parent_ids_with_it имхо как-то логичнее было бы это поле назвать parent_ids_with_self .

Я так понял, что идентификатор дерева может быть внешним ключём, когда его нет/нет необходимости привязываться к чему-то снаружи, то версия с использованием рутового узла в целом валидна (но может доставить проблем, если рутовый узел может меняться на другой)

может доставить проблем, если рутовый узел может меняться на другой

Да ладно! Если используем идентификатор рута, то почти очевидно, что это будет внешняя ссылка. А, значит, ничто не мешает организовать каскадное обновление. Правда, при изменении на другой и при этом уже существующий в таблице узел придётся вместо простого запроса использовать пляски с приседаниями (внешняя ссылка ссылается на инстанс записи в таблице, а не на само значение в ней), но если загнать логику в хранимку, проблем представлять не будет.

без использования триггеров, блокировок, дополнительных таблиц (представлений) и внешних инструментов

Но с кучей констрейнтов, и решением лишних задач в базе.

Materialized path в помощь.

Ну по сути рождённый в муках parent_ids и есть эдакий недо-materialized path.

А почему недо-? По мне так наоборот - обычный строковый материализованный путь выглядит колхозом по сравнению с этим. Или я что-то не знаю про правильные материализованные пути? Последний раз сталкивался лет 10 назад и в mysql

В отличие от классического материализованного пути массивы PostgreSQL, использованные автором, весьма затруднительно сравнивать на предмет A[] > B[], а также проверять, что A[] является префиксом B[]. А это - основные операции при работе с материализованными путями.

про "без блокировок" поржал. Тут таблица спроектирована на максимально возможное количество блокировок на каждый чих

parent_ids/Materialized path это все постгрешное? В mssql/mysql есть аналоги? (Во время чтения статьи была мысль, что parent_ids можно заменить ещё одной внешней таблицей)

а CTE отменили в той СУБД в которой автор это делал?

Не знаю как в постгре но в MS SQL и в oracle
дерево из таблицы легко собрать через обобщенные табличные выражения

еще и специальные оконные функции есть, позволяюще условия поиска корня задать и связку

Тут тебе по корню все дерево до последнего уровня еще и с номером уровня и с проверкой на цикличность при выборке

Увы, там ограничение на 256 байт.

Метка — это последовательность алфавитно-цифровых символов и знаков подчёркивания (например, в локали C допускаются символы A-Za-z0-9_). Метки должны занимать меньше 256 символов.

Примеры: 42Personal_Services

Путь метки — это последовательность из нуля или нескольких разделённых точками меток (например, L1.L2.L3), представляющая путь от корня иерархического дерева к конкретному узлу. Путь не может содержать больше 65535 меток.

Пример: Top.Countries.Europe.Russia

из той же статьи, как понимаю именно на одну метку 256 символов, а меток будет не одна, так что вполне нормально выходит

Ну да, с учётом того, что у автора ноды кодируются интами, моя ремарка неактуальна.

Рекомендую к прочтению -сегодня уже классика:

http://www.ibase.ru/treedb/

Кстати у Ibase много полезных статей по SQL. Так что вместо переизобретения велосипеда давайте оттуда статьи перепостим

Казалось бы, дал нам боженька документные бд, ту же монгу, например, куда дерево прекрасно ложится без всяких извращений.

Но нет, почему-то надо использовать реляционную структуру, которая для этого не предназначена, напихать костылей, потратить кучу времени, запихивая круглую штуку в квадратное отверстие.

А реляционные данные предлагаете в отдельной БД хранить? И как там у моего с поддержкой транзакции и всего что с ними связано?

Как правило данные можно держать где угодно. Реляционные базы лучше предназначены для много-ко-комногим. Если в данных не очень много таких отношений и не нужна нормализация до упора, то гораздо проще использовать документные бд, так как данные в бизнес-логике часто представлены в виде объектов, а документы к объектам гораздо ближе, чем строки таблиц, поэтому конверсия проходит гораздо проще.

И что с транзакциями? Они там есть.

До версии 4.0 запросы по индексу не были атомарными, если верить ВИКИ.

Версия 4.2.6 не прошла тестов на изоляцию snapshot—во.

В общем не надо путать свой карман с государственным, т.е. проверенную БД типа PostgreSQL с поделкой типа Mongo.

Как правило данные можно держать где угодно

Как правило, осознание несостоятельности этого утверждения бывает очень болезненным.

Но нет, почему-то надо использовать реляционную структуру, которая для этого не предназначена, напихать костылей, потратить кучу времени, запихивая круглую штуку в квадратное отверстие.

Если остальные данные в РСУБД, зачем заводить отдельную базу для хранения деревьев?

Хм... А как вы дерево в общем случае положите в Mongo "без извращений" - всё дерево в один документ? А если там миллион узлов?

ну это логичное развитие похода - "запихаем все дерево в один json"

Представление дерева с помощью parent_id это самый очевидный и примитивный способ представления, но он далеко не единственный и во многих (наверное, даже очень) случаях не самый удобный и эффективный.

Попробуйте иерархический идентификатор нодов ,содержащий полный путь айдишников дерева до этого нода. Айдишники можно добить нулями слева до фиксированной длины, скажем, символов 5 (вряд ли нужно больше) для облегчения парсинга. Может понравиться

Это называется "Path enumeration pattern". В общем-то все эти вещи хорошо описаны в книге Билла Корвина "SQL Antipatterns". Автор статьи просто изобретает велосипед.

Думал тут будет красивое и элегантное решение)

Честно, решение выглядит скорее как академический велосипед. В продуктовой разработке я бы такое не делал, просто по тому что ты коллегам свое решение не объяснишь, никто не поймет)

Мы используем ltree для решения подобных задач.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации