Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Скорость построения дерева, Рекурсивные CTE / 8 сообщений из 8, страница 1 из 1
02.12.2019, 02:45
    #39896882
BowMaster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скорость построения дерева, Рекурсивные CTE
Имеется у меня такой запрос, в общих чертах.
Код: 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
02.12.2019, 09:26
    #39896918
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Скорость построения дерева, Рекурсивные CTE
BowMaster,

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

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

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

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

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

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

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


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