В очередной раз в очередном проекте встречаю в очередной раз рекурсивное построение дерева структуры id - parent_id . Чуть больше сотни запросов в базу. Чуть более 100% загрузки сервера. Я согласен с тем, что программист должен быть тупым и ленивым. Но думать при этом все же нужно иногда. Есть две типовые задачи, когда нужно шерстить дерево или солидную ветку целиком. Первая - когда из-за всеобщего пофигизма и косячества, в страницу пронтенда надо выводить дерево категорий или его ветку целиком без ленивой подгрузки. И вторая, когда нужно собрать идентификаторы всех потомков начиная от какого-то узла.
Первая задача - тривиальна и должна решаться построением дерева ссылок на основ единожды слизанного списка всех узлов. Да да. Это то самый случай, когда PHP уделывает MySQL на 1-2 порядка в скорости работы. Потому что Ораклы так до сих пор и не сподобились сделать (скопипастить из большой базы ) возможность хранения деревьев в MySQL .
Вторая же задача решается за линейное время, при условии известности ( можно приблизительной ) числа уровней вложенности.
Принцип вот такой:
Это вот, например, список всех идентификаторов, начиная с текущего узла, при уровне вложенности потомков - два.
И перестаньте, наконец, делать рекурсивные запросы. MySQL этого не любит.
Первая задача - тривиальна и должна решаться построением дерева ссылок на основ единожды слизанного списка всех узлов. Да да. Это то самый случай, когда 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 этого не любит.
Комментариев нет:
Отправить комментарий