четверг, 2 октября 2014 г.

MySQL Дерево

 В очередной раз в очередном проекте встречаю в очередной раз  рекурсивное построение дерева  структуры id - parent_id .   Чуть больше сотни запросов в базу. Чуть  более  100% загрузки сервера.  Я согласен с тем, что программист должен быть тупым и ленивым. Но думать при этом все же нужно иногда.   Есть две типовые задачи, когда нужно шерстить дерево  или солидную ветку  целиком.  Первая - когда из-за  всеобщего пофигизма и косячества, в  страницу пронтенда надо выводить дерево категорий или его ветку  целиком без ленивой подгрузки. И вторая, когда нужно собрать идентификаторы всех потомков  начиная от  какого-то узла.

Первая задача - тривиальна и должна решаться построением дерева ссылок на основ единожды слизанного списка всех узлов. Да да. Это то самый случай, когда PHP уделывает MySQL на 1-2 порядка в скорости работы. Потому что  Ораклы так до сих пор и не сподобились сделать (скопипастить из большой базы ) возможность хранения деревьев в MySQL .

Вторая же задача решается за линейное время, при условии известности ( можно приблизительной ) числа уровней вложенности.
Принцип вот такой:

 
SELECT * from (
 ( SELECT :categoryId )
      union
 ( SELECT cat2.id AS id   FROM category AS cat1
          LEFT JOIN category AS cat2 ON cat2.parent_id = cat1.id
          WHERE cat1.parent_id =:categoryId and (not cat2.id is null) )
      union
 ( SELECT cat3.id AS id  FROM category AS cat1
          LEFT JOIN category AS cat2 ON cat2.parent_id = cat1.id
          LEFT JOIN category AS cat3 ON cat3.parent_id = cat2.id
          WHERE cat1.parent_id =:categoryId and (not cat3.id is null) )
) as bingo

Это вот, например, список всех идентификаторов, начиная с текущего узла, при уровне вложенности потомков  - два.

И перестаньте, наконец, делать рекурсивные запросы. MySQL этого не любит.


Комментариев нет:

Отправить комментарий