powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Скорость построения дерева, Рекурсивные CTE
8 сообщений из 8, страница 1 из 1
Скорость построения дерева, Рекурсивные CTE
    #39896882
BowMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется у меня такой запрос, в общих чертах.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
WITH RECURSIVE MyList as(
--тут большой запрос составляющий список узлов из разных таблиц
)
,
MyTree as (
  select ML."Name",ML.ID,ML."OwnerID"
  from MyList ML
  where ML."OwnerID"=0
  union all
  select ML."Name",ML.ID,ML."OwnerID"
  from MyList ML
  inner join MyTree t on (t.ID = ML."OwnerID")  --условие тут чуть сложнее, но сути не меняет 
)
select t."Name",t.ID, t."OwnerID"
from MyTree t


MyList - получаю список узлов, в таком порядке:
"Первый уровень
Первый уровень
...
Первый уровень
Второй уровень
...
Второй уровень
Третий уровень
..."
Из MyTree в итоге надо получить:
"
Имя| ID |предок|уровень
А 1 0 0
Б 10 1 1
В 100 10 2
Г 1000 100 3
Д 10000 1000 4
Е 100000 10000 5
Ж 100001 10000 5
З 11 1 1
И 101 11 2
... 3
... 4
.... 5
"
Все работает правильно. Если я задаю такие параметры для MyList, что получаю немного записей, то MyList выполняется за миллисекунды, MyTree за секунду с чем-то. Если же задаю параметры MyList такие, что получается порядка 20 000 записей, то MyList выполняется за пару секунд, а дождаться выполнения MyTree становится нереально.
Можно ли как-то ускорить работу, скажем если ограничить глубину уровней дерева, если я знаю максимальную глубину? Или же использовать другой алгоритм, может быть Nested sets?
...
Рейтинг: 0 / 0
Скорость построения дерева, Рекурсивные CTE
    #39896918
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BowMaster,

вся фишка в том, что не рекурсивная часть MyList не материализуется и будет перевыполняться каждый раз при извлечении очередного узла. Поэтому единственный вариант ускорить сей запрос — это ускорить внутренний запрос для MyList.

Запрос MyList должен быть максимально упрощён, до такой степени чтобы его хватало для построения дерева, но не более того. Остальные справочные таблицы лучше соединять уже с готовым деревом.
...
Рейтинг: 0 / 0
Скорость построения дерева, Рекурсивные CTE
    #39896937
BowMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Симонов Денис, можно добиться нужного мне результата без рекурсии?
...
Рейтинг: 0 / 0
Скорость построения дерева, Рекурсивные CTE
    #39896990
sysdba22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
можно, например, используя интервалы для обозначения принадлежности родителю:

http://gsbelarus.com/pw/articles/post/derev-ia-v-sql/

создание и и зменение таких интервалов можно автоматизировать
системой тригеров:

http://gsbelarus.com/gs/wiki/index.php/Инфраструктура_интервальных_деревьев
...
Рейтинг: 0 / 0
Скорость построения дерева, Рекурсивные CTE
    #39897069
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sysdba22,

Никто не спрашивал совета, как поменять структуру данных.
Ещё проще интервала хранить полный путь в каждом листе 0/1/10/100/1000/10000/100001
Тогда построение дерева - обычная сортировка.
...
Рейтинг: 0 / 0
Скорость построения дерева, Рекурсивные CTE
    #39898708
BowMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Проблему с перевыполнением в рекурсии MyList решил записью результата MyList во временную таблицу и считыванием в рекурсии уже из этой таблицы. Стало гораздо быстрее, но все равно недостаточно. Проблема вот в чем: когда у себя в программе делаю у запроса FetchAll, это все долго грузит. Проверка в IBExpert показывает тоже самое: после выполнения запроса MyTree вижу результаты, тяну ползунок вниз - fetch(извлечение записей) идёт долго. Решил и результат MyTree тоже записывать в таблицу и уже от туда простым SELECT получать. Это дало ускорение, но возникла другая проблема: узлы в таблицу записываются в неверном порядке. То есть запрос WITH RECURSIVE MyTree(... даёт правильный порядок, стоит поставить впереди INSERT INTO TempTable... и порядок в таблице оказывается неверный. Что можно сделать в этой ситуации?
...
Рейтинг: 0 / 0
Скорость построения дерева, Рекурсивные CTE
    #39898736
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BowMaster,

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

Код: sql
1.
2.
3.
4.
5.
6.
INSERT INTO (RN, Name, ID, OwnerID)
...
SELECT
  ROW_NUMBER() OVER() AS RN,
  t."Name",t.ID, t."OwnerID"
FROM MyTree t
...
Рейтинг: 0 / 0
Скорость построения дерева, Рекурсивные CTE
    #39898796
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BowMaster,

1 "правильный" порядок в SQL дает только ORDER BY.
2 порядка в общем случае в SQL никакого нет, это теория множеств, у них порядка нет
3 про производительность чего-кого-куда-сколько-почему_медленно - велкам на курс
"Оптимизация SQL-запросов СУБД Firebird"
http://www.ibase.ru/crs_online/
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Скорость построения дерева, Рекурсивные CTE
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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