| Автор |
Сообщение |
Phoebus
Участник форума

Зарегистрирован: 16.11.2003
Сообщ.: 30
Карма: 2 поощрить/наказать
Откуда: Minsk
|
Добавлено: Вс Янв 09, 2005 8:39 pm (написано за 8 минут 37 секунд)
Заголовок сообщения: Иерархические структуры в БД
|
|
Третьего дня возник вопрос с правильным хранением древовидных структур в СУБД типа Mysql. На форуме через поиск найти ничего не смог, поэтому и создал новую тему. Дело в том, что многие методы имеют очень большой недостаток - медлительность при проходе через все ветви (ну, вам ли объяснять!). Вот, к примеру, самый примитивный метод - указывать в каждой записи идентификатор parent-записи, типа такого: ||id||parentid||text ||1||0||sadsa ||2||0||sfafa ||3||1||sadsada ||4||2||sdadadfasf ||5||3||sdadasd где parentid==0 указывает на то, что запись является корневой. Но рекурсия в данном случае при большом количестве записей - дело страшное, да... Или вот недавно один человек предложил вообще безбашенный метод - делать только два вида записей: корневой и children, а в children класть сериализованный массив со всеми нужными записями (метод тут привел лишь для примера, не подумайте, догадываюсь, что может нехило глюкануть)... В связи с этим возник вопрос: ведь есть же и другие, более эффективные методы (типа такого, правда, у него проблемы при добавлении новых записей.. хотя...) Так вот, может кто-нибудь знает хорошие эффективные методы хранения деревьев в бд и не против ими поделиться? (особенно очень хочется услышать, что скажет по этому поводу Дмитрий Кóтеров...) Заранее Спасибо.
|
|
| Вернуться к началу |
|
 |
Rumata
Профессионал

Зарегистрирован: 17.08.2003
Сообщ.: 1772
Карма: 167 поощрить/наказать
|
Добавлено: Вс Янв 09, 2005 8:57 pm (спустя 17 минут; написано за 4 минуты 1 секунду)
Заголовок сообщения:
|
|
вообще-то это уже обсуждалось здесь и где-то на http://xpoint.ru
еще рекоммендую погуглить/пояндексить на тему Nested Sets приведенная Вами ссылка имеет переводы на русском, но мне кажется и оригинал и переводы грешат ошибками в запросах SQL
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
|
| Вернуться к началу |
|
 |
Graymur
Участник форума
Зарегистрирован: 13.07.2004
Сообщ.: 57
Карма: 0 поощрить/наказать
Откуда: Севастополь
|
|
| Вернуться к началу |
|
 |
Константин Жинько [tIT]
Сотрудник «Лаборатории»

Зарегистрирован: 12.06.2004
Сообщ.: 2265
Карма: 111 поощрить/наказать
Откуда: Москва
|
Добавлено: Вт Янв 11, 2005 12:55 pm (спустя 2 часа 25 минут; написано за 6 минут 21 секунду)
Заголовок сообщения:
|
|
| Phoebus писал(а): |
|
самый примитивный метод - указывать в каждой записи идентификатор parent-записи, типа такого |
Я все время так и делал, и скорость меня устраивала даже
| Phoebus писал(а): |
|
при большом количестве записей |
Способ действительно самый примитивный... Например для организации каталога магазина http://arbois.ru я делал именно так и прогонял с достаточно реальным количеством записей... Всегда думала меньше секунды, как на виндах, так и на фре... Сейчас там структура каталога немного изменилась, а следовательно и логика алгоритма (из-за другого представления), но принцип дерева тот же. [offtop] Мда... только что туда заглянул -- каталог, мягко говоря, на стадии тестирования...% И зачем заказывали, раз не пользуются?% С жиру, видимо, бесятся... [/offtop] А Вам для каких целей нужно дерево? Для какого приложения?
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Вт Янв 11, 2005 11:16 pm (спустя 10 часов 20 минут; написано за 46 секунд)
Заголовок сообщения:
|
|
Phoebus:
Из личного опыта могу все-таки посоветовать id-parentid , все эти Nested Sets это все чепуха, в большинстве случаев оптимальным решением будет именно такой способ. Сам на это напарывался уже.
|
|
| Вернуться к началу |
|
 |
Phoebus
Участник форума

Зарегистрирован: 16.11.2003
Сообщ.: 30
Карма: 2 поощрить/наказать
Откуда: Minsk
|
Добавлено: Чт Янв 13, 2005 3:52 pm (спустя 1 день 16 часов 35 минут; написано за 2 минуты 53 секунды)
Заголовок сообщения:
|
|
| tIT писал(а): |
|
А Вам для каких целей нужно дерево? Для какого приложения? |
CMS Конкретнее: а) друвовидная структуризация документов (т.е. каталог/подкаталог/документ, вложенность любого вида) б) древовидные комментарии (как в lj)
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Чт Янв 13, 2005 8:51 pm (спустя 4 часа 59 минут; написано за 41 секунду)
Заголовок сообщения:
|
|
Phoebus
Для а) однозначно id-parentid, а для б) ИМХО больше подойдет именно Nested Sets.
|
|
| Вернуться к началу |
|
 |
Евгений Галашин
Модератор

Зарегистрирован: 29.12.2003
Сообщ.: 1862
Карма: 30 поощрить/наказать
|
Добавлено: Чт Янв 13, 2005 8:59 pm (спустя 8 минут; написано за 6 секунд)
Заголовок сообщения:
|
|
yUAC
а) почему?
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Чт Янв 13, 2005 9:58 pm (спустя 58 минут; написано за 34 секунды)
Заголовок сообщения:
|
|
Евгений Галашин
Это намного более гибкая структура, и с ней намного проще работать. И тут не критично немного большее количество запросов
|
|
| Вернуться к началу |
|
 |
Phoebus
Участник форума

Зарегистрирован: 16.11.2003
Сообщ.: 30
Карма: 2 поощрить/наказать
Откуда: Minsk
|
Добавлено: Пт Янв 14, 2005 3:19 pm (спустя 17 часов 20 минут; написано за 7 минут 32 секунды)
Заголовок сообщения:
|
|
Странно.... я как-раз таки думал совсем по другому, т.е. nested sets использовать для хранения документов, потому что их добавлением занимается лишь ограниченный круг людей => небольшие тормоза при INSERT не будут столь существенны. В отличие от комментариев, которые добавляются намного чаще, вложенность будет использоваться чаще (возможно) и поэтому тут INSERT (который очень быстр в методе id-parentid) не менее важен чем SELECT... впрочем, в последнем случае действительно при выборке могут возникнуть тормоза т.к. выводить мне придется все деревья целиком, от корня до самого нижнего child-a...
| yUAC писал(а): |
|
И тут не критично немного большее количество запросов |
Ну, вообще да, что-то я об этом не подумал... Просто мысли были забиты статейкой (замечательная вещь! ) оффтопом:
| Дмитрий Кóтеров писал(а): |
Сходите, пожалуйста, в Поиск по запросу «Nested Sets». Спасибо!  |
Я, естесвенно, в поиске искал все что мог придумать касаясь "иерархический" и "древовидный", а вот "nested sets" абсолютно из памяти вылетело ;)
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Сб Янв 15, 2005 10:11 pm (спустя 1 день 6 часов 52 минуты; написано за 5 минут 2 секунды)
Заголовок сообщения:
|
|
| Phoebus писал(а): |
|
которые добавляются намного чаще, вложенность будет использоваться чаще (возможно) и поэтому тут INSERT (который очень быстр в методе id-parentid) не менее важен чем SELECT |
Дело в том, что INSERT начинает проявлять свои «тормоза» на Nested Sets только при количестве записей начиная от 100. В комментариях конечно такого быть не может, а если даже и может, то SELECT в данном случае ИМХО намного более важен - просмотров комментариев по идее должно быть намного больше, чем добавлений комментариев (если база грамотно спроектирована, конечно).
| Phoebus писал(а): |
|
Просто мысли были забиты статейкой |
У меня в свое время тоже. Потом пришлось от этой мысли отказаться - слишком сложно (хотя это не самая большая проблема), а главное - не нужно!
| Phoebus писал(а): |
|
nested sets использовать для хранения документов, потому что их добавлением занимается лишь ограниченный круг людей |
Ну и что! Вам же не нужно для хранения документов сразу выводить все дерево! Nested Sets как раз нужен тогда, когда необходимо хранить большое количество документов в строгой иерархии, и при этом каждый раз по полдерева доставать. А если это делается для сайта, то тут несколько конкретных запросов по полю parentid будут работать быстрее, чем один запрос на выборку всей ветки документов, и последующего разбора этой ветки. Если не поняли, то могу привести пример (писать лень, если действительно не поняли, то напишу)
|
|
| Вернуться к началу |
|
 |
Phoebus
Участник форума

Зарегистрирован: 16.11.2003
Сообщ.: 30
Карма: 2 поощрить/наказать
Откуда: Minsk
|
Добавлено: Пн Янв 17, 2005 3:35 pm (спустя 1 день 17 часов 23 минуты; написано за 3 минуты 56 секунд)
Заголовок сообщения:
|
|
| yUAC писал(а): |
|
последующего разбора этой ветки. Если не поняли, то могу привести пример |
Нет, все ясно, спасибо ;) Единственное, хочу спросить: ощутимы ли будут тормоза если используя метод Nested Sets хранить данные о комментариях (т.е. где текста мало чаще всего) в той же таблице что и древовидные отношения dbtree? Т.е. добавить к столбцам id|lft|rgt еще и username|commentstext|email, а не разделять их на две таблицы со связью по id - сильно ли упадет скорость прохода по дереву?
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Пн Янв 17, 2005 4:05 pm (спустя 30 минут; написано за 37 секунд)
Заголовок сообщения:
|
|
| Phoebus писал(а): |
|
сильно ли упадет скорость прохода по дереву |
Неа. Я так делал - скорость от этого не зависит, а если и зависит, то несильно.
|
|
| Вернуться к началу |
|
 |
Vladimir Sergeev
Участник форума
Зарегистрирован: 18.02.2004
Сообщ.: 89
Карма: 11 поощрить/наказать
|
Добавлено: Ср Янв 19, 2005 7:25 pm (спустя 2 дня 3 часа 20 минут; написано за 16 минут 50 секунд)
Заголовок сообщения:
|
|
У меня стояла задача в дереве для объекта получить с максимальной скоростью всех его родителей и обработать их. Собственно, Nestsd Sets и иже с ним сразу отпали, я стал использовать `id`-`parent_id`-`level`. Однако, никакой рекурсии использовать я тоже не стал - все манипуляции по извлечению родителей уместилиь в два SQL-запроса: один получает по ID объекта его level, а другой level раз связывает таблицу саму с собой, выдавая ID родителей. Все работает довольно быстро. У меня система контрля доступа, дерево юзеров(забил 100 000, уровень вложения - до 25), дерево объектов(те же числа) и таблица с записями привелегий(забил 150 000 записей). Вся работа: связывание таблиц сначала самих с собой, потом друг с другом, в том числе и обработка полученной из БД инфы, занимает 0,05 с. В этом контексте на все про все использовались уже 4 запроса. Что интересно, время обработки практически одинаково и для 5 объектов, и для 100 000 - слава MySQL!:) Кстати, при таком подходе в MySQL3 масимальный уровень вложения не может превышать 31. (действует ограничение на число связываемых таблиц)
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Ср Янв 19, 2005 7:44 pm (спустя 18 минут; написано за 5 секунд)
Заголовок сообщения:
|
|
Bred Vilchec
А можно примерчик запроса?
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
Добавлено: Ср Янв 19, 2005 8:16 pm (спустя 32 минуты; написано за 4 минуты 30 секунд)
Заголовок сообщения:
|
|
Видимо, что-то типа
| Код (SQL): |
скопировать код в буфер обмена |
SELECT t1.*, t2.*, ... FROM tree t1 RIGHT JOIN tree t2 ON t2.parent=t1.id RIGHT JOIN tree t3 ON t3.parent=t2.id ... WHERE t1.id=? |
Ну или что-то типа того. Причем число JOIN-ов совпадает с глубиной дерева. Можно просто все 31 уровня сразу забить - тогда там автоматом с некоторого момента пойдут NULL-ы, и выберутся потомки до максимум 32-го уровня (я, правда, не уверен - может, нужно запрос чуть-чуть подкорректировать). В принципе, тоже вариант, и работать должно довольно быстро (с чего б ему долго работать, если он выбирает ровно столько записей, сколько нужно).
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Ср Янв 19, 2005 8:20 pm (спустя 4 минуты; написано за 12 секунд)
Заголовок сообщения:
|
|
Дмитрий Кóтеров
Очень интересное решение ;)
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
Добавлено: Ср Янв 19, 2005 9:46 pm (спустя 1 час 26 минут; написано за 59 секунд)
Заголовок сообщения:
|
|
Осталось только его на практике как-нибудь проверить. Но - пока не подвернулось задачи. В принципе, 32 - это очень значительный уровень для большинства деревьев. Я так даже навскидку и не могу представить задачи, где бы его оказалось недостаточно.
|
|
| Вернуться к началу |
|
 |
Константин Жинько [tIT]
Сотрудник «Лаборатории»

Зарегистрирован: 12.06.2004
Сообщ.: 2265
Карма: 111 поощрить/наказать
Откуда: Москва
|
Добавлено: Ср Янв 19, 2005 10:34 pm (спустя 48 минут; написано за 29 секунд)
Заголовок сообщения:
|
|
| Bred Vilchec писал(а): |
|
Кстати, при таком подходе в MySQL3 масимальный уровень вложения не может превышать 31. |
Поэтому в больших виртальных магазинах лучше все-таки рекурсию
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Ср Янв 19, 2005 10:36 pm (спустя 1 минуту 50 секунд; написано за 49 секунд)
Заголовок сообщения:
|
|
| Да все равно выигрыш мизерный... Особенно если нет затрат на передачу данных по сети - можно делать сколько угодно запросов, самое главное - чтобы сама нагрузка на базу данных была не очень высокая
|
|
| Вернуться к началу |
|
 |
Константин Жинько [tIT]
Сотрудник «Лаборатории»

Зарегистрирован: 12.06.2004
Сообщ.: 2265
Карма: 111 поощрить/наказать
Откуда: Москва
|
Добавлено: Ср Янв 19, 2005 10:43 pm (спустя 6 минут; написано за 3 секунды)
Заголовок сообщения:
|
|
| резонно
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
Добавлено: Ср Янв 19, 2005 11:31 pm (спустя 47 минут; написано за 1 минуту 1 секунду)
Заголовок сообщения:
|
|
| yUAC, не совсем ты прав, как мне кажется. Тут штука в том, что может потребоваться, к примеру, не выбрать все, а подсчитать число чего-то. Например, вычислить число товаров в разделах, имя предка (произвольного!) которых начинается на "А".
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Ср Янв 19, 2005 11:54 pm (спустя 23 минуты; написано за 1 минуту 34 секунды)
Заголовок сообщения:
|
|
Дмитрий Кóтеров
Ух закрутил... В таком случае бедной СУБД придется перебирать ВСЮ базу, и тут уже не имеет особого значения, как составлен запрос - с такими «финтами ушами», или без.
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
Добавлено: Чт Янв 20, 2005 12:08 am (спустя 13 минут; написано за 21 секунду)
Заголовок сообщения:
|
|
| Ты забыл про индексы. Совсем и не факт, что ей придется перебирать всю базу.
|
|
| Вернуться к началу |
|
 |
Vladimir Sergeev
Участник форума
Зарегистрирован: 18.02.2004
Сообщ.: 89
Карма: 11 поощрить/наказать
|
Добавлено: Чт Янв 20, 2005 8:14 am (спустя 8 часов 6 минут)
Заголовок сообщения:
|
|
Во-первых, прошу не забывать, что ограничение в 31 уровень справедливо только для MySQL 3, в четвертой версии число связываемых таблиц увеличено. Поэтому можно смело использовать этот подход, тем более если магазин такой крутой, то проблема отсталого хостинга для него не актуальна. Позже поковыряюсь в документации и найду точные числа. Вот структура таблицы:
| Код (SQL): |
скопировать код в буфер обмена |
CREATE TABLE `users_tree` ( `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, `parent_id` int(11) UNSIGNED NOT NULL DEFAULT '0', `level` smallint(6) UNSIGNED NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `parent_id` (`parent_id`,`level`) ) ENGINE=MyISAM DEFAULT CHARSET=cp1251; |
Сразу скажу, я далеко не спец в проектировании и оптимизации БД, поэтому уверен, что есть и более рациональные способы расставить индексы в таблице. Для каждого юзера в отдельной таблице хранится его имя(оно используется крайне редко). А вот и реальный запрос, собираемый скриптом по кусочкам:
| Код (SQL): |
скопировать код в буфер обмена |
SELECT @user0 := tbl0.id, @user1 := tbl1.id, @user2 := tbl2.id, @user3 := tbl3.id, @user4 := tbl4.id, @user5 := tbl5.id FROM users_tree AS tbl0, users_tree AS tbl1, users_tree AS tbl2, users_tree AS tbl3, users_tree AS tbl4, users_tree AS tbl5 WHERE tbl0.id = '102' AND tbl1.id = tbl0.parent_id AND tbl2.id = tbl1.parent_id AND tbl3.id = tbl2.parent_id AND tbl4.id = tbl3.parent_id AND tbl5.id = tbl4.parent_id AND tbl5.parent_id =0 |
Результат этого запроса скрипт даже не получает, ведь следующий запрос использует установленые переменные. Кстати, я в ближайшее время допишу класс к контроллеру доступа и скорее всего выложу его в "Готовые решения", приходите посмотреть:)
| tIT писал(а): |
|
Поэтому в больших виртальных магазинах лучше все-таки рекурсию |
Если я не ошибаюсь, в рекурсии число запросов будет равно уровню вложения объекта? Не слишком ли "жирно" получается, ведь как мы знаем, основное время уходит на получение результата запроса? Тем более, сама рекурсия достаточно жадна до ресурсов.
|
|
| Вернуться к началу |
|
 |
Vladimir Sergeev
Участник форума
Зарегистрирован: 18.02.2004
Сообщ.: 89
Карма: 11 поощрить/наказать
|
Добавлено: Чт Янв 20, 2005 9:04 am (спустя 49 минут; написано за 21 минуту 34 секунды)
Заголовок сообщения:
|
|
Сегодня все утро насиловал БД:), хотел посмотреть, насколько размер и вложенность данных влияют на скорость работы. Вбил в БД еще по 1 000 000(!) случайных пользователей, объектов и привелегий, общий размер базы превысил 220 Мб. Самый "младший" в иерархии пользователь имел уровень вложенности 30, а самый "младший" объект - 32. Выяснение отношения пользователя 863786 к объекту 934355 заняло всего 0.972 секунды! Этот результат оказался средним среди аналогичных тестов на больших вложениях. А сколько бы делал это рекурсивный скрипт? При том, надо заметить, у меня далеко не мощная машина - Celeron 2000 и 256 Mb RAM. После этого я провел еще один маленький тест - циклом 1000 раз выяснял, имеет ли случайный пользователь права на случайный объект. Цикл занял чуть менее 200 секунд, это значит, что на одну итерацию приходилось по 0,2 секунды. Думаю, эти результы(как увелечительное стекло) являются весомым аргументом в пользу возложения "грязной" работы на БД. PS если кому-либо интересно, могу поделиться тестирующими скриптами, однако одно маленькое "но": заполнение БД занимает часа два-три, если не больше.:)
|
|
| Вернуться к началу |
|
 |
Евгений Галашин
Модератор

Зарегистрирован: 29.12.2003
Сообщ.: 1862
Карма: 30 поощрить/наказать
|
Добавлено: Чт Янв 20, 2005 11:11 am (спустя 2 часа 7 минут; написано за 22 секунды)
Заголовок сообщения:
|
|
| Bred Vilchec: +2
|
|
| Вернуться к началу |
|
 |
Константин Жинько [tIT]
Сотрудник «Лаборатории»

Зарегистрирован: 12.06.2004
Сообщ.: 2265
Карма: 111 поощрить/наказать
Откуда: Москва
|
Добавлено: Чт Янв 20, 2005 4:18 pm (спустя 5 часов 6 минут; написано за 1 минуту 10 секунд)
Заголовок сообщения:
|
|
| Bred Vilchec писал(а): |
Если я не ошибаюсь, в рекурсии число запросов будет равно уровню вложения объекта? Не слишком ли "жирно" получается, ведь как мы знаем, основное время уходит на получение результата запроса? Тем более, сама рекурсия достаточно жадна до ресурсов. |
Так и есть (-; Но у меня почему-то все быстро работало при условии, что СУБД на той же машине, что и Apache.
|
|
| Вернуться к началу |
|
 |
Константин Жинько [tIT]
Сотрудник «Лаборатории»

Зарегистрирован: 12.06.2004
Сообщ.: 2265
Карма: 111 поощрить/наказать
Откуда: Москва
|
Добавлено: Чт Янв 20, 2005 4:20 pm (спустя 2 минуты; написано за 6 секунд)
Заголовок сообщения:
|
|
| Bred Vilchec писал(а): |
После этого я провел еще один маленький тест - циклом 1000 раз выяснял, имеет ли случайный пользователь права на случайный объект. Цикл занял чуть менее 200 секунд, это значит, что на одну итерацию приходилось по 0,2 секунды. |
Великолепно! +1
|
|
| Вернуться к началу |
|
 |
Vladimir Sergeev
Участник форума
Зарегистрирован: 18.02.2004
Сообщ.: 89
Карма: 11 поощрить/наказать
|
Добавлено: Чт Янв 20, 2005 5:06 pm (спустя 45 минут; написано за 15 минут 5 секунд)
Заголовок сообщения:
|
|
Могу предпринять только симметричные ответные меры: Евгений Галашин+2 tIT+1 :) Спасибо. PS карму надо повышать не мне, а разработчикам MySQL.
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
Добавлено: Чт Янв 20, 2005 6:57 pm (спустя 1 час 50 минут; написано за 2 минуты 38 секунд)
Заголовок сообщения:
|
|
| Bred Vilchec писал(а): |
|
`level` smallint(6) UNSIGNED NOT NULL DEFAULT '0', |
Не пойму только, зачем Вам level. По идее, его всегда можно вычислить тем же SQL-запросом (см. конструкцию MySQL IF()). И - еще один момент. Как Вы обходитесь без LEFT JOIN (или RIGHT JOIN)? Тот запрос, который Вы выше привели, по идее, работать не должен - ведь, например, в tbl5 не найдется соответствующего элемента (если максимальная вложенность в базе - 4), и будет возвращен пустой результат.
|
|
| Вернуться к началу |
|
 |
Юрий Насретдинов
Модератор

Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237 поощрить/наказать
Откуда: 007 495
|
Добавлено: Чт Янв 20, 2005 7:42 pm (спустя 45 минут; написано за 17 секунд)
Заголовок сообщения:
|
|
Дмитрий Кóтеров
А это просто другой вид JOIN`а
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
Добавлено: Чт Янв 20, 2005 8:24 pm (спустя 41 минуту; написано за 29 секунд)
Заголовок сообщения:
|
|
| yUAC, спасибо. А и Б - это просто разные буквы алфавита. ;-)
|
|
| Вернуться к началу |
|
 |
Vladimir Sergeev
Участник форума
Зарегистрирован: 18.02.2004
Сообщ.: 89
Карма: 11 поощрить/наказать
|
Добавлено: Пт Янв 21, 2005 3:36 am (спустя 7 часов 12 минут; написано за 3 минуты 10 секунд)
Заголовок сообщения:
|
|
| Дмитрий Кóтеров писал(а): |
|
Тот запрос, который Вы выше привели, по идее, работать не должен - ведь, например, в tbl5 не найдется соответствующего элемента (если максимальная вложенность в базе - 4), и будет возвращен пустой результат. |
Собственно вот за этим-то level и нужен. Это, конечо, некоторая избыточность хранимых данных, но по сравнению с Nested Sets и dbtree не такая уж и большая.
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
Добавлено: Пт Янв 21, 2005 7:16 pm (спустя 15 часов 39 минут; написано за 53 секунды)
Заголовок сообщения:
|
|
Еще раз: очень вероятно, что при использовании LEFT JOIN-а никакой level не нужен. Эх, сейчас попробую все-таки написать тестовый скрипт. Ждите.
|
|
| Вернуться к началу |
|
 |
Vladimir Sergeev
Участник форума
Зарегистрирован: 18.02.2004
Сообщ.: 89
Карма: 11 поощрить/наказать
|
Добавлено: Пт Янв 21, 2005 8:14 pm (спустя 58 минут; написано за 9 минут 45 секунд)
Заголовок сообщения:
|
|
Оки, теперь я понял Вашу идею. Жду с нетерпением, особенно хотелось бы увидеть таинственный запрос с if'ами. В принципе, если это сработает, это будет здорово, однако в моем приложении level все же необходим. Как я уже говорил, у меня 4 запроса: первый получает level'ы второй и третий связывают сами с собой таблицы юзеров и объектов а вот четвертый, основной, связывает три таблицы и фактически выдает мне результат, allow или denied. Вся соль в том, что в ходе этого запроса мне необходимо "пробежать" всех родителей пользоватлей (они получены 2-м запросом), начиная с корневого, а также всех родителей объектов(они получены в 3-ем запросе), отсортировав их именно по level. Есть конечно кривой обходной путь - сортировать по id, мол у кого id меньше, тот и младше. Но мне он тоже не подойдет, поскольку возможен перенос объекта или пользователя в другую ветку, при этом, естественно, все такие "тонкие" связи нарушатся.
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
Добавлено: Пт Янв 21, 2005 10:23 pm (спустя 2 часа 8 минут; написано за 10 минут 22 секунды)
Заголовок сообщения:
|
|
Собственно, все получилось. Вот скрипт: http://dbtree.dklab.ru/search.php
Таблица очень проста: (id, parent, text). Индексы по всем полям. В качестве эксперимента я туда вбил содержимое своего виртуального диска в Денвере (около 84694 файлов и директорий). Имена файлов и директорий пошли в поле text. Запрос к скрипту задается в формате: /имя/имя/имя/... (поиск относительно корня) или имя/имя/... (поиск относительно произвольной ветки!) где имя - это любая LIKE-маска, которая будет подставлена на соответствующее место в пути. Например: - запрос "/" вернет все элементы; - запрос "/home" - только те, что в /home - запрос "www" - вернет все содержимое всех директорий www - и т.д. Глубина выборки показывает, на сколько элементов вглубь нужно копать. Отображаются не все результаты поиска, а только первые N (см. соответствующее поле). Наконец, флажок "Подсчитывать число записей" заставляет перед основным запросом выполнить запрос с COUNT(), который подсчитает общее число записей. Это довольно долго, если записей много. Обратите внимание, что сами директории НЕ отображаются. Например, в результате http://dbtree.dklab.ru/search.php?mask=%2Fhome&depth=3&num=100&count=on - нет элемента "/" и "/home". Однако, если директория пуста, то тогда она отобразится, например: http://dbtree.dklab.ru/search.php?mask=%2Ftmp%2F%21sendmail&depth=3&num=100&count=on. таким образом, действуют правила: отображаются только листовые элементы! К счастью, по листовым вершинам можно легко восстановить всех родителей чисто на PHP (все имена и ID-шники для этого в результатах имеются). Вообще, чисто на MySQL сделать выборку не только листовых вершин, но вообще всех, похоже, нельзя. Внизу, под результатами, показывается сам SQL-запрос. Вывод: на мой взгляд, работает все очень хорошо. Единственное место, где возможны тормоза, - это подсчет числа потомков некоторого элемента, если таких потомков много, и разветвленность дерева большая. В этом, пожалуй, выигрывают Nested Sets.
|
|
| Вернуться к началу |
|
 |
Дмитрий Кóтеров
Администратор

Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405 поощрить/наказать
|
Добавлено: Пт Янв 21, 2005 10:25 pm (спустя 2 минуты; написано за 1 минуту 11 секунд)
Заголовок сообщения:
|
|
| Да, еще одно. Если "глубина копания" превышает фактическую глубину дерева, на быстродействие это отрицательным образом не сказывается. Иными словами, если у вас есть дерево с максимальной вложенностью 10, то можно делать запросы с вложенностью 30 - тормозить по сравнению с вложенностью 10 не будет.
|
|
| Вернуться к началу |
|
 |
Ant
Сотрудник «Лаборатории»

Зарегистрирован: 17.06.2003
Сообщ.: 6804
Карма: 121 поощрить/наказать
|
Добавлено: Сб Янв 22, 2005 12:51 am (спустя 2 часа 25 минут; написано за 51 секунду)
Заголовок сообщения:
|
|
|
«.ru» не забудьте добавить, кому надо попасть на страницу.
|
|
| Вернуться к началу |
|
 |
|