Как лучше хранить дерево в реляционной БД

6yrop

чтобы запрос: выбрать всех потомков заданного узла, формулировался на SQL просто?

Marinavo_0507

префикс хранить для каждого узла

SvinkaVJeansah

В виде
create table mytree (
node text/blob/varchar primary key,
node_content char(33) default "хуй",
node_fk text/blob/varchar - вероятно, не понадобится);
Правда в таком варианте мы ограничиваем кол-во прямых потомков узла, но зато, чтоб найти всех потомков узла
"abdrgefystem" просто берем node like "abdrgefystem%";

6yrop

что такое префикс?

Marinavo_0507

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

KViH

в Oracle чтоб такие запросы делать есть START WITH и CONNECT BY

6yrop

да, в Оракле что-то было такое, но, к сожалению, у нас что-то дешевое типа MySQL

6yrop

а пронумеровывать узлы как-нибудь хитро нельзя?

zya369

"видел" два подхода (не считая префиксов, конечно - ибо ацтой )
первый - таблица ссылается сама на себя. Получать всех потомков или предков, учитывая вложенность, - довольно геморно
второй - особо не вникал, но там заводятся для каждого элемента два числа - условно, left и right - и по ним определяется местоположение в дереве
В этом случае изменение места в дереве происходит геморно (надо все переиндексивровать а всевозможные рекурсивные выбори - просто (выборка типа "выбрать всех у кого нет потомков" имеет вид "where (right - left) = 1" (вроде бы так
За подробностями - в гугл

zya369

вот, нашел какую-то статейку
статейка

artimon

Вот чувак заморачивался этим вопросом.
http://dull.ru/keyword/trees/

6yrop

всем спасибо

tokuchu

Юзай LDAP , или же можешь посмотреть как они реализуют хранение дерева.

Fragaria

а в чём отстойность метода, если в качестве префикса юзать например путь в виде x.y.z, где x,y,z - соответственно номера узлов на каждом уровне?

Marinavo_0507

Для глубоких деревьев хранить (и обновлять при модификациях) нужно много.

ava3443

Поле будет типа VARCHAR, надо полагать?
И какой индекс ты для такого префикса будешь использовать?

SvinkaVJeansah

Не нужно, если ограничить заранее количество прямых потомков у узла. Исключение - перемещение поддерева в другую точку.

Marinavo_0507

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

Fragaria

ну да, varchar, а с каких пор они не индексируются?
ЗЫ зато очень просто найти нужные данные, просто найти всех предков и потомков, это наглядно, легко добавляются новые узлы, особенно когда неважен порядок непосредственных дочерних элементов каждого узла.

SvinkaVJeansah

А так, что если у нас максимум, например, 2 потомка, то мы юзаем 1010.....; если больше, то выделяем на адресацию каждого узла соответствующее количество разрядов.
Чтоб выбрать подузлы понятно, что делать.

Fragaria

тогда и вложенность ограничивается, хотя моим способом - тоже

SvinkaVJeansah

Вложенность ограничивается длинной поля.

Marinavo_0507

Всё равно при глубине дерева N будут храниться пути длиной O(N). Без этого ограничения - O(N*ln(N - небольшая разница.

SvinkaVJeansah

Тут надо думать над конкретной задачей, видимо ) Все и сразу - это только в сказке...

Fragaria

это можно обойти, сделав поле с путём как text =) только резко упадёт скорость выборки

Marinavo_0507

> это можно обойти, сделав поле с путём как text
длина путей от этого уменьшится?

Fragaria

длина - нет, просто ограничение на длину исчезнет, но пропадёт возможность индексировать по этому полю

ava3443

> ну да, varchar, а с каких пор они не индексируются?
они конечно индексируются, только ты почитай, как именно.
Оставить комментарий
Имя или ник:
Комментарий: