imho.ws |
![]() |
![]() |
![]() |
# 1 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
Проблемы с построением "дерева"(+)
Решил тут написать каталог, простенький. Взял банальный алгоритм(не помню как он называется):
ID-PARENT_ID т.е. каждая ветка знает своего родителя. рекурсивной функцией строю дерево. решил провести тест. заполнил базу 10000 записями. причем, каждая ветка имеет 1 потомка. т.е. получается 10к запросов вида: select * from table where parentid = id apache падает(а может и не он). понимаю что в реальности такой алгоритм медленный и тяжелый, но мне просто нужно было проверить. что интересно, ASP.NET+IIS справляется, хотя и долго. собственно в чем могут быть грабли(я имею ввиду настройки php, apache, mysql)? p.s. про другие алгоритмы знаю, но некогда их реализовывать, да и для этой задачи - пустая трата времени. p.p.s. hard&soft: athlon xp1700+, 512 DDR winxp sp1 eng. apache 1.3.x php 4.3.9(как модуль). mysql 3.23.58 d-max-nt кстати 5-ый php, опять же - как модуль, "съел" - 6k записей, после чего вывод на страницу просто остановился. p.p.p.s. добавил принудителньое закрытие mysql соединения после каждого запроса. Похоже виновата все же mysql. Теперь под php4 также просто останавливается вывод. может кто подскажит утилиту(поудобнее), чтобы смотреть текущие connections и queries для mysql. к сожалению mysql administrator требует mysql 4.x.
__________________
убрано по просьбе администратора ![]() Последний раз редактировалось Sheryld; 27.01.2005 в 16:57. |
![]() |
![]() |
# 7 | ||
мод
IMHO Кодер-200(6,7,8) Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Цитата:
Цитата:
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям! Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru Pahan-Hubbitus. |
||
![]() |
![]() |
# 8 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
вот скрипт:
Код:
class Category { var $categoryInfo = array( "id"=>0, "parent_id"=>0, "level"=>0, "title"=>"", "desc"=>"", "creation_date"=>"", "modify_date"=>"", "photo"=>""); var $categoryInfoCollection = array(); function Category() { //default constructor } ................ function GetCategoryByParentID($categoryParentID) { $db = new MySql(null,"mport3",null,null); $db->MySql_Connect(); $db->MySql_SelectDb(); $selectQuery = "select * from category where cat_PARENTID = ". $categoryParentID; $db->MySql_QueryDb($selectQuery); //echo $selectQuery; if ($db->dbResult != null) { while($row = mysql_fetch_assoc($db->dbResult)) { $this->categoryInfo['id'] = $row['cat_ID']; $this->categoryInfo['parent_id'] = $row['cat_PARENTID']; $this->categoryInfo['level'] = $row['cat_NODELEVEL']; $this->categoryInfo['title'] = $row['cat_TITLE']; $this->categoryInfo['desc'] = $row['cat_DESC']; $this->categoryInfo['creation_date'] = $row['cat_CREATION_DATE']; $this->categoryInfo['modify_date'] = $row['cat_MODIFY_DATE']; $this->categoryInfo['photo'] = $row['cat_PHOTO_URL']; $this->categoryInfoCollection[] = $this->categoryInfo; } return 0; } return -1; } ................ } Код:
function Tree($categoryParentID) { $category = new Category(); if ($category->GetCategoryByParentID($categoryParentID) == 0) { if (!empty($category->categoryInfoCollection)) { foreach($category->categoryInfoCollection as $categoryInfoItem) { echo $categoryInfoItem["title"] . " " . $categoryInfoItem["parent_id"] . "<BR>\r\n"; Tree($categoryInfoItem["id"]); } } } } Код:
class MySql { var $dbServer = ""; var $dbName = ""; var $dbUser = ""; var $dbPass = ""; var $dbConn; var $dbResult; var $dbErrorNumber = 0; var $dbErrorMessage = ""; var $debugFromHanlder = ""; /*function MySql() { //default constructor }*/ function MySql($dbServer = null, $dbName = null, $dbUser = null, $dbPass = null) { //default constructor if ($dbServer != null) { $this->dbServer = $dbServer; } if ($dbName != null) { $this->dbName = $dbName; } if ($dbUser != null) { $this->dbUser = $dbUser; } if ($dbPass != null) { $this->dbPass = $dbPass; } } function MySql_Connect() { if (!isset($this->dbConn) || $this->dbConn == null) { $this->dbConn = @mysql_connect( $this->dbServer, $this->dbUser, $this->dbPass); $this->MySql_ErrorHanlder("connect"); } } function MySql_SelectDb() { if (isset($this->dbName) && $this->dbName != null) { @mysql_select_db($this->dbName,$this->dbConn); $this->MySql_ErrorHanlder("select"); } } function MySql_QueryDb($dbQuery) { if (isset($dbQuery) && $dbQuery != null) { $this->dbResult = @mysql_query($dbQuery,$this->dbConn); //echo $dbQuery; $this->MySql_ErrorHanlder("query"); if (@mysql_num_rows($this->dbResult) == 0) { $this->dbResult=null; } } } function MySql_Close() { if (isset($this->dbConn) || $this->dbConn != null) { @mysql_close($this->dbConn); $this->MySql_ErrorHanlder("close"); } } function MySql_Free() { @mysql_free($this->dbResult); $this->MySql_ErrorHanlder("free"); } function MySql_ErrorHanlder($debugFromHanlder) { $this->dbErrorNumber = mysql_errno(); $this->dbErrorMessage = mysql_error(); if ($this->dbErrorNumber != 0) { echo $this->dbErrorNumber . " " . $this->dbErrorMessage; echo " " . $debugFromHanlder . "<BR>\r\n"; } $this->dbErrorNumber = 0; $this->dbErrorMessage = ""; } }
__________________
убрано по просьбе администратора ![]() Последний раз редактировалось Sheryld; 28.01.2005 в 20:19. |
![]() |
![]() |
# 12 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
мой класс проходит свободно 500 уровней вложенности. потом начинаются проблемы.
про nested sets я знаю. но не хочу его применять, т.к. в этом проекте он не нужен, а там много времени уйдет на реализацию... а что можно оптимизировать? мой интерес чисто теоритический, т.к. в реальных приложениях я ограничиваю вложенность до 100 категорий(на данном алгоритме). p.s. за файлик спасибо...
__________________
убрано по просьбе администратора ![]() Последний раз редактировалось Sheryld; 28.01.2005 в 20:18. |
![]() |
![]() |
# 14 |
Junior Member
Регистрация: 04.03.2004
Сообщения: 56
![]() |
2 Sheryld
Я сильно с алгоритмом не разбирался, но вот, что сразу броилось в глаза (оно большого прироста не даст, но так приятнее работать ![]() Код: Код:
$this->categoryInfo['id'] = $row['cat_ID']; $this->categoryInfo['parent_id'] = $row['cat_PARENTID']; $this->categoryInfo['level'] = $row['cat_NODELEVEL']; $this->categoryInfo['title'] = $row['cat_TITLE']; $this->categoryInfo['desc'] = $row['cat_DESC']; $this->categoryInfo['creation_date'] = $row['cat_CREATION_DATE']; $this->categoryInfo['modify_date'] = $row['cat_MODIFY_DATE']; $this->categoryInfo['photo'] = $row['cat_PHOTO_URL']; $this->categoryInfoCollection[] = $this->categoryInfo; Код:
$this->categoryInfoCollection[] = $row; И, наконец, главное. Учитывая, что допустимы 100 уровней вложенности, я бы все-таки дважды подумал, прежде чем использовать рекурсию для дерева. IMHO Лишняя нагрузка серверу ни к чему. |
![]() |
![]() |
# 16 |
Junior Member
Регистрация: 04.03.2004
Сообщения: 56
![]() |
Чтобы не заморачиваться, можно, например, ввести еще одну таблицу следующей структуры:
Код:
treeid INTEGER AUTOINCREMENT path TEXT id INTEGER Используя такую таблицу можно легко получить любую ветку дерева одним запросом с условием LIKE. Не самый лучший способ, но будет на порядок эффективнее, чем рекурсия. Последний раз редактировалось dacuan; 01.02.2005 в 14:50. |
![]() |
![]() |
# 17 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
такой алгоритм тоже знаю, но в принципе против него, т.к. нарушаются условия нормализации.
к тому же его следует применять, имхо, только если есть в наличии ms sql server 2K, например. чтобы повесить основные операции по поддержке дерева на триггеры. т.е. получить структуру саму себя поддерживающую. в принципе уже каркас написал. по первым тестам(искуственным) работает весьма шустро, если скрестить с кешем - то самое оно. ежели на реальном тесте производительность сильно ухудшится, то наверное возьму за основу nested sets. у меня там каталог полностью "кастомный", т.е. помимо менеджмента категорий там еще предполагается, что каждая единица в категории имеет неограниченное, настраиваемое число параметров определенных заранее типов(joins, joins, joins).
__________________
убрано по просьбе администратора ![]() |
![]() |
![]() |
# 18 | |||||
Junior Member
Регистрация: 04.03.2004
Сообщения: 56
![]() |
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
|||||
![]() |
![]() |
# 20 |
Full Member
Регистрация: 29.05.2002
Сообщения: 544
![]() ![]() ![]() ![]() ![]() |
а как скажем сделать такую вещь(при таком классе nested sets): сортировка каждой ветки дерева но с сохранением порядка.
пример: должно быть: Код:
аа бб вв а_в б_в Код:
аа а_в бб б_в вв p.s. при рекурсивном алгоритме можно получить такой список сразу...
__________________
убрано по просьбе администратора ![]() |
![]() |