powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Тяпничный nested-set
25 сообщений из 27, страница 1 из 2
Тяпничный nested-set
    #38932889
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день коллеги.

Традиционно в БД для представления деревьев используют списки смежности.
К недостаткам такого варианта можно отнести сложность движения от корня
к самому дальнему потомку и массовые выборки.

Есть интерес - попробовать NestedSet
http://en.wikipedia.org/wiki/Nested_set_model

И написать несколько реализаций такого базового интерфейса.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
template<class Node>
class NestedSet{
 public:
 virtual void insertRootNode(Node node);
 virtual void insertNode(Node node,Node parent);
 virtual void dropNodes(int left,int right);
 virtual NodeIterator selectChildNodes(Node node);
}


Какие вопросы нужно решить?

По какой формуле расчитывать Left, Right?

Как уплотнять или двигать границы NestedSet если Node вставить уже невозможно (Right-Left)<1

Оптимизация итератора

Оптимизация для популярных БД (MSSQL, Oracle, MySQL)

P.S. Сорь за возможные огрехи в описании базового интерфейса. Надеюсь суть будет ясна и так.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933113
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

ух, позавчера прочёл эту статью. Интересовался разными моделями данных.
Правда, у меня пока интерес теоретический.

При беглом ознакомлении у меня возникли следующие мысли. В такой модели вставки работают медленно, как их улучшить? Возьмём пример каталога с одеждой. Мужская имеет индексы с 2 по 9. Если нужно будет добавить что-то, то придётся пересчитывать много индексов. А почему бы не сделать их с большими пропусками? Например, мужской одежде назначить изначально индексы с 2 по 900 (или 9000, или 9000000). Мужским костюмам индексы дать с 3 по 80 (а не 8). Таким образом пересчитывать все индексы придётся гораздо реже, лишь когда отведённое про запас место кончится.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933126
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Насколько я понимаю, модель NestedSet предполагает очень редкие модификации дерева.
Например - работа со справочником. Классификатором. Или конфигурацией оконного
выпадающего меню.

По поводу диапазона цифирок Left, Right. Можно взять 0 и 10^38 (макимальное значение
NUMBER поля для Oracle). Но будет-ли это рационально с точки зрения хранения?
Многие БД хранят числа в квази-текстовом формате. BinHex, BCD.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933152
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вставку можно порешать пустотами. Т.е. не нумеровать 1,2,3... а 10,20,30... надо вставить между 20-30 делаешь 25 и т.д. Тогда в худшем случае (например станет 25,26,27 и надо вставить между 25-26) потребуется перенумировать небольшой кусок.

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

И предусматривать пакетную вставку, чтобы сразу дать блок данных, чтобы сразу распределить боле-мене равномерно.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933163
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonМожно взять 0 и 10^38 (макимальное значение NUMBER поля для Oracle). Но будет-ли это рационально с точки зрения хранения?
Это будет нерационально с точки зрения скорости выборки. Чем больше размер значения, тем медленнее операция сравнения двух значений.
Тестил в свое время на MSSQL скорости используя GUID и обычный ID int(4). C GUID`ами скорости в разы медленнее, да и понятно, т.к. он в 4 раза больше места занимает (16 байт против 4х).
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933180
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Была оригинальная идея. Я хотел ее обсудить.

Дерево Штерна.



Это бесконечная последовательность рациональных чисел которые замкнуты в интервал от 0 до 1. И генерить
их очень удобно. Для вставок в дочерние узлы. И схема получается весьма элегантная.

Но к сожалению я не знаю как рациональные дроби прикрутить к БД.

Тоесть такой вариант

Код: plsql
1.
2.
3.
4.
5.
6.
create table nestedset(
  id number,
  name varchar2(2000),
  left RATIONAL,
  right RATIONAL
);


С рациональным (гипотетическим типом). Но в Оракле это не взлетит т.к. оракл не позволяет
перегружать типы.

Может взлетит в MSSQL/.Net с их новыми возможностиями по интеграции ДотНет кода и СКЛ машины.
Если в форуме есть МССКЛ-щики то пусть поправят.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933182
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Стоп.

Не от 0 до 1. А от нуля до плюс положительной бесконечности.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933197
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Или такой вариант.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
create table nestedset(
  id number,
  name varchar2(2000),
  left_numerator number,
  left_denominator number,
  right_numerator number,
  right_denominator number
);


Чисто математически - взлетает но про поддержку БД в сортировках и сравнениях придётся забыть.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933203
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonБыла оригинальная идея. Я хотел ее обсудить.

Дерево Штерна.
Оно двоичное. Как третий узел вставить?

maytonНо к сожалению я не знаю как рациональные дроби прикрутить к БД.
Не надо их туда крутить. Как их сравнивать? Каждый раз приводить к одному знаменателю?
Хранить десятичное с высокой точностью тоже не вариант, чем больше размер значения, тем медленнее операция сравнения двух значений.
int 4 байта идеальный вариант.

ИМХУ тут идеального алгоритма вставки не придумать на все случаи жизни. Надо исходить из задачи: одно дело поштучно вставлять в разные части дерева, другое - сразу блок записей в одну ноду.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933235
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Там кстати еще одна большая проблема: отсортировать по Name внутри одного уровня вложенности.

Например там в примере select ... order by Left чудесным образом даст отсортированный справочник на всех уровнях вложенности, читай построчно и выводи, но не дай бог потребуется переименовать какой-нибудь верхний узел так что он переедет в другой конец, например Women`s в Girl`s.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933248
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тебе подобные запросы ничего не напоминают?
Код: plaintext
1.
2.
3.
4.
5.
SELECT DISTINCT Child.Node, Child.Left, Child.Right
FROM Tree AS Child, Tree AS Parent 
WHERE Parent.Left < Child.Left AND Parent.Right > Child.Right  -- associate Child Nodes with ancestors
GROUP BY Child.Node, Child.Left, Child.Right
HAVING MAX(Parent.Left) = 1 


Помнишь как быстро считалось select`ом перекрытие диапазонов IP-шников?
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933351
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TНе надо их туда крутить. Как их сравнивать? Каждый раз приводить к одному знаменателю?

Ну... ты вроде-бы в теории чисел не новичок. Сравнение дробей - суть умножение числителей и знаменателей крест-на-крест.
И сравнение. Достаточно простая формула совершенно не требующая расчёта НОД.

P.S. В тему был мой топик о золотых треугольниках .. к сож не могу найти.

Хранить десятичное с высокой точностью тоже не вариант, чем больше размер значения, тем медленнее операция сравнения двух значений. int 4 байта идеальный вариант.

Насчёт хранения приближённого числа которое может быть использовано в поиске (по аналогии с хеш-кодом) я много
думал. Можно рядом положить вещественное чтобы (грубо) отсекать те data-rows которые ну 100% не попадают
в интервал поиска. Но покая я не определился с критерием точности - поскипаю эту оптимизацию. Хотя она
интересна.

По поводу int32 - полностью согласен. Это чрезвычайно длинная последовательность особенно с формулой Штерна
когда при движении вправо-вниз мы инкременируем числитель а влево-вниз - знаменатель у нас получается
очень медленный рост счётчика который при обычном режиме sequence в БД (справочник или классификатор)
переполнится только через много много лет.

ИМХУ тут идеального алгоритма вставки не придумать на все случаи жизни. Надо исходить из задачи: одно дело поштучно вставлять в разные части дерева, другое - сразу блок записей в одну ноду.
Да. Я думаю что дерево Штерна не будет иметь особого перформанса для вставки.
Но я предлагаю исходить из того что на 0.1% вставок в справочник приходится примерно
99.9% чтений (full-table-scan).
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933353
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TОно двоичное. Как третий узел вставить?
Ну... оно вобщем-то никакое. Не двоичное и не троичное. К преимуществу
этого дерева я могу отнести то что промежуточные узлы в которых нет
потомков - можно удалить. И при этом структура сохраняется. Ведь
семантическая связь идёт с корнем только через Left, Right и больше ничего
не нужно.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933363
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TТам кстати еще одна большая проблема: отсортировать по Name внутри одного уровня вложенности.

Например там в примере select ... order by Left чудесным образом даст отсортированный справочник на всех уровнях вложенности, читай построчно и выводи, но не дай бог потребуется переименовать какой-нибудь верхний узел так что он переедет в другой конец, например Women`s в Girl`s.
В создающем скрипте я не указал поле depth. Я честно говоря не знаю нужно оно
или нет. С точки зрения оптимизации поиска... вроде-бы нужно. Если мы выбираем
всех потомков Node1 у которой уровень равен 5 то можно сразу отсекать всех кто меньше 5.
И наоборот. Если это гео-классификатор городов и стран и улиц и домов то можно ограничить поиск
городами с другой стороны.

Сразу сходу добавлю что nested-set скорее всего не выдержит конкуренции с обычным
сильно-ветвящимся деревом который мы можем закодить в С++ с использованием
коллекций в узлах.

Но я надеюсь что алгоритмы расчёта Left/Right могут быть полезны в реляционных БД. Там где
технически нет возможности вложить data-row коллекцию ссылок на другие data-row.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933372
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вобщем... буду последователен.

Накатываю патчик на создающий скрипт.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
create sequence ns_pk;

create table nestedset(
  id number primary key, -- This is fucken PK. Or Not? It it nessesary?
  name varchar2(2000),  -- This is fucken body of Node. Is it possible to use 'TYPE'? Idntknw.
  depth number not null, 
  l1 number not null,
  l2 number not null,
  r1 number not null,
  r2 number not null
);



Я кое-что изменил. Не люблю длинные имена. Пускай числитель и знаменатель для Left/Right будут просто 1-м и 2-м числом.
Для краткости формул.

Еще остались нерешённые вопросы.

Где будет PK? Теоретически комбинация двух числителей и знаменателей уже является PK.

Нужно-ли кешировать результат деления? В каких запросах это поможет и какова будет возможная погрешность?

Тестовая выборка? Откуда взять? За неимением гео-классификатора я просто возьму кусок своей файловой системы
где узлы - это каталоги.

Тестовые запросы. Какие они должны быть? Надо оценить точечные (OLTP) на выборку. И выборка целых поддеревьев.
Если представить что мы работаем с GUI и пользователь кликает по TreeControl и раскрывает классификаторы.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933415
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonDima TНе надо их туда крутить. Как их сравнивать? Каждый раз приводить к одному знаменателю?

Ну... ты вроде-бы в теории чисел не новичок. Сравнение дробей - суть умножение числителей и знаменателей крест-на-крест.
И сравнение. Достаточно простая формула совершенно не требующая расчёта НОД.
Я про НОД не писал :) Именно одно сравнение и два умножения против одного сравнения. Разница в скорости на порядок, если не больше.

maytonВ создающем скрипте я не указал поле depth. Я честно говоря не знаю нужно оно
или нет. С точки зрения оптимизации поиска... вроде-бы нужно.
Вроде толку от него немного. Хотел написать что ты про него забыл, но примера зачем он нужен не придумал.

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

Про nested-set сегодня впервые от тебя узнал, если честно. Сначала очарование - затем осознание и разочарование. Вот и написал что с ходу в глаза бросилось. Потом почитал инет, есть польза для быстрого охвата диапазона, элементарно быстро за раз средствами SQL посчитать что-то связанное с конкретным узлом. Тут очень эффективно сверху охватывется все что внизу, поэтому я бы лучше добавил классическое parent_id, которое позволяет эффективно идти снизу вверх.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933425
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonГде будет PK? Теоретически комбинация двух числителей и знаменателей уже является PK.

PK должен быть абстрактный. Просто счетчик (или GUID) не связанный ни с чем. Не надо никогда предавать другие смыслы PK, мизерная оптимизация обернется гигансткими проблемами, например на него ссылается 100500 записей дочерних таблиц, а тебе надо его немного поменять потому что его смысл поменялся.

maytonНужно-ли кешировать результат деления? В каких запросах это поможет и какова будет возможная погрешность?

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

maytonТестовая выборка? Откуда взять? За неимением гео-классификатора я просто возьму кусок своей файловой системы
где узлы - это каталоги.

Тестовые запросы. Какие они должны быть? Надо оценить точечные (OLTP) на выборку. И выборка целых поддеревьев.
Если представить что мы работаем с GUI и пользователь кликает по TreeControl и раскрывает классификаторы.

по хорошему надо какую-то реальную задачу. Файловая система - задача не очень, хотя обычные к ней запросы идеально оптимизируются:
1. Сколько файлов в папке
2. выбрать файлы по маске из папки с подпапками.
Для второго надо parent_id чтобы полный путь восстановить.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933431
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я всегда очень пристальное внимание уделяю тестовой выборке. Мда. Файловая система
- не очень т.к. я не смогу придумать актуальных запросов.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933434
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tmaytonпропущено...

Ну... ты вроде-бы в теории чисел не новичок. Сравнение дробей - суть умножение числителей и знаменателей крест-на-крест.
И сравнение. Достаточно простая формула совершенно не требующая расчёта НОД.
Я про НОД не писал :) Именно одно сравнение и два умножения против одного сравнения. Разница в скорости на порядок, если не больше.
Запутал ты меня своими теориями чисел, два произведения мелочь :)

Главное: невозможно использовать индексы, т.к. результат сравнения зависит от обоих значений, т.е. всегда тупой перебор декартова произведения. А это супер тормоз.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933438
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Помнишь я говорил про краеугольный камень современных dbms (heap organized tables).
Для них невозможо построить план table-scan с участием предиката

WHERE a1 < x and x < a2;

?

Этот вопрос частично решают spatial-системы. Которые шуршат по картографии
но это тема очень specific. И не все БД поддерживают spatial запросы.

И в этой теме я вобщем-то подразумеваю FTS. Единственное дополнение - можно
фильтровать по depth или только по left к примеру.

Или можно сегментировать таблицу по подтипам. Но это суть - выборка из разных
таблиц с предусловием. С последующим union.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933439
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonДля них невозможо построить план table-scan с участием предиката

Тьху. Я имею в виду невозможно использовать эффективно два индекса.
Обычно или левый или правый.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933448
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TПро nested-set сегодня впервые от тебя узнал, если честно. Сначала очарование - затем осознание и разочарование. Вот и написал что с ходу в глаза бросилось. Потом почитал инет, есть польза для быстрого охвата диапазона, элементарно быстро за раз средствами SQL посчитать что-то связанное с конкретным узлом. Тут очень эффективно сверху охватывется все что внизу, поэтому я бы лучше добавил классическое parent_id, которое позволяет эффективно идти снизу вверх.
Это не последний способ. Еще есть материализация маршрута. Когда в ключе хранят путь.

idpathdepth0Clothing01Clothing/Men's12Clothing/Men's/Suits23Clothing/Woman's1

Способ достаточно быстрый и жлобский. Но неудобно делать манипуляции родительских вершин.
И лавинообразно растёт использование диска.

Впрочем я такой способ видел в одной биллинговой БД.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38933458
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonЭто не последний способ. Еще есть материализация маршрута. Когда в ключе хранят путь.
тоже читал, но имху это еще большая экзотика. Пользы очень мало.
maytonя такой способ видел в одной биллинговой БД.
Я тоже разные извраты видел, но не могу сказать что это от большого ума, чаще от желания внедрить что-то нестандартное. Жажда творчества неистребима :)
maytonПомнишь я говорил про краеугольный камень современных dbms (heap organized tables).
Для них невозможо построить план table-scan с участием предиката
WHERE a1 < x and x < a2;
Потому что никто ничего не придумал лучше теории реляционных бд. Может и придумал, но по этой теории столько понаделано, что переделывать никто не будет. Поэтому надо подстраиваться под то что есть, иначе любая иновационная поделка упрется в полную несовместимость с наделанным, и это будет не в пользу поделки. Хотя если придумают что-то реально мощнее реляционных бд - со временем они уйдут.
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38937730
ДохтаР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonПомнишь я говорил про краеугольный камень современных dbms (heap organized tables).
Для них невозможо построить план table-scan с участием предиката

WHERE a1 < x and x < a2;

?

Этот вопрос частично решают spatial-системы. Которые шуршат по картографии
но это тема очень specific. И не все БД поддерживают spatial запросы.

И в этой теме я вобщем-то подразумеваю FTS. Единственное дополнение - можно
фильтровать по depth или только по left к примеру.

Или можно сегментировать таблицу по подтипам. Но это суть - выборка из разных
таблиц с предусловием. С последующим union.

Велосипед

В стебельковых срачах, эта тема вкратце обсуждалась.
Я даже приблизительный класс аллокатора выкладывал .
Жаль что тему в Других СУБД удалили .
...
Рейтинг: 0 / 0
Тяпничный nested-set
    #38937775
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо док. Я стебельковые читал и немало. Но про m-tree чет не помню.

Но в любом случае спасибо.
...
Рейтинг: 0 / 0
25 сообщений из 27, страница 1 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / Тяпничный nested-set
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]