Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

Иерархические структуры в БД (Phoebus)
Goto page 1, 2, 3  Next
Author Message
Phoebus
Участник форума



Joined: 16 Nov 2003
Posts: 30
Карма: 2
   поощрить/наказать

Location: Minsk

PostPosted: Sun Jan 09, 2005 8:39 pm (написано за 8 минут 37 секунд)
   Post subject: Иерархические структуры в БД
Reply with quote

Третьего дня возник вопрос с правильным хранением древовидных структур в СУБД типа Mysql. На форуме через поиск найти ничего не смог, поэтому и создал новую тему.
Дело в том, что многие методы имеют очень большой недостаток - медлительность при проходе через все ветви (ну, вам ли объяснять!).
Вот, к примеру, самый примитивный метод - указывать в каждой записи идентификатор parent-записи, типа такого:
||id||parentid||text
||1||0||sadsa
||2||0||sfafa
||3||1||sadsada
||4||2||sdadadfasf
||5||3||sdadasd
где parentid==0 указывает на то, что запись является корневой. Но рекурсия в данном случае при большом количестве записей - дело страшное, да...

Или вот недавно один человек предложил вообще безбашенный метод - делать только два вида записей: корневой и children, а в children класть сериализованный массив со всеми нужными записями (метод тут привел лишь для примера, не подумайте, догадываюсь, что может нехило глюкануть)...

В связи с этим возник вопрос: ведь есть же и другие, более эффективные методы (типа такого, правда, у него проблемы при добавлении новых записей.. хотя...) Так вот, может кто-нибудь знает хорошие эффективные методы хранения деревьев в бд и не против ими поделиться?
(особенно очень хочется услышать, что скажет по этому поводу Дмитрий Кóтеров...)

Заранее Спасибо.
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1845
Карма: 178
   поощрить/наказать


PostPosted: Sun Jan 09, 2005 8:57 pm (спустя 17 минут; написано за 4 минуты 1 секунду)
   Post subject:
Reply with quote

вообще-то это уже обсуждалось здесь и где-то на http://xpoint.ru
еще рекоммендую погуглить/пояндексить на тему Nested Sets

приведенная Вами ссылка имеет переводы на русском, но мне кажется и оригинал и переводы грешат ошибками в запросах SQL
Back to top
View user's profile Send private message Visit poster's website
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Mon Jan 10, 2005 5:00 am (спустя 8 часов 3 минуты; написано за 9 секунд)
   Post subject: Nested Sets
Reply with quote

Сходите, пожалуйста, в Поиск по запросу «Nested Sets». Спасибо! ;-)
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Graymur
Участник форума



Joined: 13 Jul 2004
Posts: 57
Карма: 0
   поощрить/наказать

Location: Севастополь

PostPosted: Tue Jan 11, 2005 10:30 am (спустя 1 день 5 часов 29 минут; написано за 5 секунд)
   Post subject:
Reply with quote

http://www.livejournal.com/~demiurg/53125.html?mode=reply
Back to top
View user's profile Send private message Visit poster's website
Константин Жинько [tIT]
Сотрудник «Лаборатории»



Joined: 12 Jun 2004
Posts: 2265
Карма: 108
   поощрить/наказать

Location: Москва

PostPosted: Tue Jan 11, 2005 12:55 pm (спустя 2 часа 25 минут; написано за 6 минут 21 секунду)
   Post subject:
Reply with quote

Phoebus wrote:
самый примитивный метод - указывать в каждой записи идентификатор parent-записи, типа такого
Я все время так и делал, и скорость меня устраивала даже
Phoebus wrote:
при большом количестве записей
Способ действительно самый примитивный... Например для организации каталога магазина http://arbois.ru я делал именно так и прогонял с достаточно реальным количеством записей... Всегда думала меньше секунды, как на виндах, так и на фре...
Сейчас там структура каталога немного изменилась, а следовательно и логика алгоритма (из-за другого представления), но принцип дерева тот же.
[offtop]
Мда... только что туда заглянул -- каталог, мягко говоря, на стадии тестирования...%
И зачем заказывали, раз не пользуются?%
С жиру, видимо, бесятся...
[/offtop]
А Вам для каких целей нужно дерево? Для какого приложения?
Back to top
View user's profile Send private message ICQ Number
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Tue Jan 11, 2005 11:16 pm (спустя 10 часов 20 минут; написано за 46 секунд)
   Post subject:
Reply with quote

Phoebus:
Из личного опыта могу все-таки посоветовать id-parentid , все эти Nested Sets это все чепуха, в большинстве случаев оптимальным решением будет именно такой способ. Сам на это напарывался уже.
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Phoebus
Участник форума



Joined: 16 Nov 2003
Posts: 30
Карма: 2
   поощрить/наказать

Location: Minsk

PostPosted: Thu Jan 13, 2005 3:52 pm (спустя 1 день 16 часов 35 минут; написано за 2 минуты 53 секунды)
   Post subject:
Reply with quote

tIT wrote:
А Вам для каких целей нужно дерево? Для какого приложения?
CMS
Конкретнее:
а) друвовидная структуризация документов (т.е. каталог/подкаталог/документ, вложенность любого вида)
б) древовидные комментарии (как в lj)
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Thu Jan 13, 2005 8:51 pm (спустя 4 часа 59 минут; написано за 41 секунду)
   Post subject:
Reply with quote

Phoebus
Для а) однозначно id-parentid, а для б) ИМХО больше подойдет именно Nested Sets.
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Евгений Галашин
Модератор



Joined: 29 Dec 2003
Posts: 1862
Карма: 31
   поощрить/наказать


PostPosted: Thu Jan 13, 2005 8:59 pm (спустя 8 минут; написано за 6 секунд)
   Post subject:
Reply with quote

yUAC
а) почему?
Back to top
View user's profile Send private message ICQ Number
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Thu Jan 13, 2005 9:58 pm (спустя 58 минут; написано за 34 секунды)
   Post subject:
Reply with quote

Евгений Галашин
Это намного более гибкая структура, и с ней намного проще работать. И тут не критично немного большее количество запросов
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Phoebus
Участник форума



Joined: 16 Nov 2003
Posts: 30
Карма: 2
   поощрить/наказать

Location: Minsk

PostPosted: Fri Jan 14, 2005 3:19 pm (спустя 17 часов 20 минут; написано за 7 минут 32 секунды)
   Post subject:
Reply with quote

yUAC wrote:
yUAC
Странно.... я как-раз таки думал совсем по другому, т.е. nested sets использовать для хранения документов, потому что их добавлением занимается лишь ограниченный круг людей => небольшие тормоза при INSERT не будут столь существенны. В отличие от комментариев, которые добавляются намного чаще, вложенность будет использоваться чаще (возможно) и поэтому тут INSERT (который очень быстр в методе id-parentid) не менее важен чем SELECT... впрочем, в последнем случае действительно при выборке могут возникнуть тормоза т.к. выводить мне придется все деревья целиком, от корня до самого нижнего child-a...
yUAC wrote:
И тут не критично немного большее количество запросов
Ну, вообще да, что-то я об этом не подумал... Просто мысли были забиты статейкой (замечательная вещь! ;-) )

оффтопом:
Дмитрий Кóтеров wrote:
Сходите, пожалуйста, в Поиск по запросу «Nested Sets». Спасибо! ;-)
Я, естесвенно, в поиске искал все что мог придумать касаясь "иерархический" и "древовидный", а вот "nested sets" абсолютно из памяти вылетело ;)
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Sat Jan 15, 2005 10:11 pm (спустя 1 день 6 часов 52 минуты; написано за 5 минут 2 секунды)
   Post subject:
Reply with quote

Phoebus wrote:
которые добавляются намного чаще, вложенность будет использоваться чаще (возможно) и поэтому тут INSERT (который очень быстр в методе id-parentid) не менее важен чем SELECT
Дело в том, что INSERT начинает проявлять свои «тормоза» на Nested Sets только при количестве записей начиная от 100. В комментариях конечно такого быть не может, а если даже и может, то SELECT в данном случае ИМХО намного более важен - просмотров комментариев по идее должно быть намного больше, чем добавлений комментариев (если база грамотно спроектирована, конечно).
Phoebus wrote:
Просто мысли были забиты статейкой
У меня в свое время тоже. Потом пришлось от этой мысли отказаться - слишком сложно (хотя это не самая большая проблема), а главное - не нужно!
Phoebus wrote:
nested sets использовать для хранения документов, потому что их добавлением занимается лишь ограниченный круг людей
Ну и что! Вам же не нужно для хранения документов сразу выводить все дерево! Nested Sets как раз нужен тогда, когда необходимо хранить большое количество документов в строгой иерархии, и при этом каждый раз по полдерева доставать. А если это делается для сайта, то тут несколько конкретных запросов по полю parentid будут работать быстрее, чем один запрос на выборку всей ветки документов, и последующего разбора этой ветки. Если не поняли, то могу привести пример (писать лень, если действительно не поняли, то напишу)
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Phoebus
Участник форума



Joined: 16 Nov 2003
Posts: 30
Карма: 2
   поощрить/наказать

Location: Minsk

PostPosted: Mon Jan 17, 2005 3:35 pm (спустя 1 день 17 часов 23 минуты; написано за 3 минуты 56 секунд)
   Post subject:
Reply with quote

yUAC wrote:
последующего разбора этой ветки. Если не поняли, то могу привести пример
Нет, все ясно, спасибо ;)
Единственное, хочу спросить: ощутимы ли будут тормоза если используя метод Nested Sets хранить данные о комментариях (т.е. где текста мало чаще всего) в той же таблице что и древовидные отношения dbtree? Т.е. добавить к столбцам id|lft|rgt еще и username|commentstext|email, а не разделять их на две таблицы со связью по id - сильно ли упадет скорость прохода по дереву?
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Mon Jan 17, 2005 4:05 pm (спустя 30 минут; написано за 37 секунд)
   Post subject:
Reply with quote

Phoebus wrote:
сильно ли упадет скорость прохода по дереву
Неа. Я так делал - скорость от этого не зависит, а если и зависит, то несильно.
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Vladimir Sergeev
Участник форума



Joined: 18 Feb 2004
Posts: 89
Карма: 11
   поощрить/наказать


PostPosted: Wed Jan 19, 2005 7:25 pm (спустя 2 дня 3 часа 20 минут; написано за 16 минут 50 секунд)
   Post subject:
Reply with quote

У меня стояла задача в дереве для объекта получить с максимальной скоростью всех его родителей и обработать их.
Собственно, 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.
(действует ограничение на число связываемых таблиц)
Back to top
View user's profile Send private message ICQ Number
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jan 19, 2005 7:44 pm (спустя 18 минут; написано за 5 секунд)
   Post subject:
Reply with quote

Bred Vilchec
А можно примерчик запроса?
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Wed Jan 19, 2005 8:16 pm (спустя 32 минуты; написано за 4 минуты 30 секунд)
   Post subject:
Reply with quote

Видимо, что-то типа
Code (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-го уровня (я, правда, не уверен - может, нужно запрос чуть-чуть подкорректировать). В принципе, тоже вариант, и работать должно довольно быстро (с чего б ему долго работать, если он выбирает ровно столько записей, сколько нужно).
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jan 19, 2005 8:20 pm (спустя 4 минуты; написано за 12 секунд)
   Post subject:
Reply with quote

Дмитрий Кóтеров
Очень интересное решение ;)
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Wed Jan 19, 2005 9:46 pm (спустя 1 час 26 минут; написано за 59 секунд)
   Post subject:
Reply with quote

Осталось только его на практике как-нибудь проверить. Но - пока не подвернулось задачи.
В принципе, 32 - это очень значительный уровень для большинства деревьев. Я так даже навскидку и не могу представить задачи, где бы его оказалось недостаточно.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Константин Жинько [tIT]
Сотрудник «Лаборатории»



Joined: 12 Jun 2004
Posts: 2265
Карма: 108
   поощрить/наказать

Location: Москва

PostPosted: Wed Jan 19, 2005 10:34 pm (спустя 48 минут; написано за 29 секунд)
   Post subject:
Reply with quote

Bred Vilchec wrote:
Кстати, при таком подходе в MySQL3 масимальный уровень вложения не может превышать 31.
Поэтому в больших виртальных магазинах лучше все-таки рекурсию
Back to top
View user's profile Send private message ICQ Number
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jan 19, 2005 10:36 pm (спустя 1 минуту 50 секунд; написано за 49 секунд)
   Post subject:
Reply with quote

Да все равно выигрыш мизерный... Особенно если нет затрат на передачу данных по сети - можно делать сколько угодно запросов, самое главное - чтобы сама нагрузка на базу данных была не очень высокая
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Константин Жинько [tIT]
Сотрудник «Лаборатории»



Joined: 12 Jun 2004
Posts: 2265
Карма: 108
   поощрить/наказать

Location: Москва

PostPosted: Wed Jan 19, 2005 10:43 pm (спустя 6 минут; написано за 3 секунды)
   Post subject:
Reply with quote

резонно
Back to top
View user's profile Send private message ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Wed Jan 19, 2005 11:31 pm (спустя 47 минут; написано за 1 минуту 1 секунду)
   Post subject:
Reply with quote

yUAC, не совсем ты прав, как мне кажется. Тут штука в том, что может потребоваться, к примеру, не выбрать все, а подсчитать число чего-то. Например, вычислить число товаров в разделах, имя предка (произвольного!) которых начинается на "А".
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jan 19, 2005 11:54 pm (спустя 23 минуты; написано за 1 минуту 34 секунды)
   Post subject:
Reply with quote

Дмитрий Кóтеров
Ух закрутил... В таком случае бедной СУБД придется перебирать ВСЮ базу, и тут уже не имеет особого значения, как составлен запрос - с такими «финтами ушами», или без.
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Thu Jan 20, 2005 12:08 am (спустя 13 минут; написано за 21 секунду)
   Post subject:
Reply with quote

Ты забыл про индексы. Совсем и не факт, что ей придется перебирать всю базу.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Vladimir Sergeev
Участник форума



Joined: 18 Feb 2004
Posts: 89
Карма: 11
   поощрить/наказать


PostPosted: Thu Jan 20, 2005 8:14 am (спустя 8 часов 6 минут)
   Post subject:
Reply with quote

Во-первых, прошу не забывать, что ограничение в 31 уровень справедливо только для
MySQL 3
, в четвертой версии число связываемых таблиц увеличено.
Поэтому можно смело использовать этот подход, тем более если магазин такой крутой, то проблема отсталого хостинга для него не актуальна.
Позже поковыряюсь в документации и найду точные числа.

Вот структура таблицы:
Code (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;
Сразу скажу, я далеко не спец в проектировании и оптимизации БД, поэтому уверен,
что есть и более рациональные способы расставить индексы в таблице.
Для каждого юзера в отдельной таблице хранится его имя(оно используется крайне редко).

А вот и реальный запрос, собираемый скриптом по кусочкам:
Code (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 wrote:
Поэтому в больших виртальных магазинах лучше все-таки рекурсию
Если я не ошибаюсь, в рекурсии число запросов будет равно уровню вложения объекта?
Не слишком ли "жирно" получается, ведь как мы знаем, основное время уходит на получение результата запроса?
Тем более, сама рекурсия достаточно жадна до ресурсов.
Back to top
View user's profile Send private message ICQ Number
Vladimir Sergeev
Участник форума



Joined: 18 Feb 2004
Posts: 89
Карма: 11
   поощрить/наказать


PostPosted: Thu Jan 20, 2005 9:04 am (спустя 49 минут; написано за 21 минуту 34 секунды)
   Post subject:
Reply with quote

Сегодня все утро насиловал БД:), хотел посмотреть, насколько размер и вложенность
данных влияют на скорость работы. Вбил в БД еще по 1 000 000(!) случайных пользователей,
объектов и привелегий, общий размер базы превысил 220 Мб.
Самый "младший" в иерархии пользователь имел уровень вложенности 30,
а самый "младший" объект - 32.

Выяснение отношения пользователя 863786 к объекту 934355 заняло всего 0.972 секунды!
Этот результат оказался средним среди аналогичных тестов на больших вложениях.
А сколько бы делал это рекурсивный скрипт?
При том, надо заметить, у меня далеко не мощная машина - Celeron 2000 и 256 Mb RAM.

После этого я провел еще один маленький тест - циклом 1000 раз выяснял, имеет ли случайный пользователь
права на случайный объект. Цикл занял чуть менее 200 секунд, это значит, что на одну итерацию
приходилось по 0,2 секунды.

Думаю, эти результы(как увелечительное стекло) являются весомым аргументом в пользу
возложения "грязной" работы на БД.

PS если кому-либо интересно, могу поделиться тестирующими скриптами, однако одно маленькое "но":
заполнение БД занимает часа два-три, если не больше.:)
Back to top
View user's profile Send private message ICQ Number
Евгений Галашин
Модератор



Joined: 29 Dec 2003
Posts: 1862
Карма: 31
   поощрить/наказать


PostPosted: Thu Jan 20, 2005 11:11 am (спустя 2 часа 7 минут; написано за 22 секунды)
   Post subject:
Reply with quote

Bred Vilchec: +2
Back to top
View user's profile Send private message ICQ Number
Константин Жинько [tIT]
Сотрудник «Лаборатории»



Joined: 12 Jun 2004
Posts: 2265
Карма: 108
   поощрить/наказать

Location: Москва

PostPosted: Thu Jan 20, 2005 4:18 pm (спустя 5 часов 6 минут; написано за 1 минуту 10 секунд)
   Post subject:
Reply with quote

Bred Vilchec wrote:
Если я не ошибаюсь, в рекурсии число запросов будет равно уровню вложения объекта?
Не слишком ли "жирно" получается, ведь как мы знаем, основное время уходит на получение результата запроса?
Тем более, сама рекурсия достаточно жадна до ресурсов.
Так и есть (-;
Но у меня почему-то все быстро работало при условии, что СУБД на той же машине, что и Apache.
Back to top
View user's profile Send private message ICQ Number
Константин Жинько [tIT]
Сотрудник «Лаборатории»



Joined: 12 Jun 2004
Posts: 2265
Карма: 108
   поощрить/наказать

Location: Москва

PostPosted: Thu Jan 20, 2005 4:20 pm (спустя 2 минуты; написано за 6 секунд)
   Post subject:
Reply with quote

Bred Vilchec wrote:
После этого я провел еще один маленький тест - циклом 1000 раз выяснял, имеет ли случайный пользователь
права на случайный объект. Цикл занял чуть менее 200 секунд, это значит, что на одну итерацию
приходилось по 0,2 секунды.
Великолепно!
+1
Back to top
View user's profile Send private message ICQ Number
Vladimir Sergeev
Участник форума



Joined: 18 Feb 2004
Posts: 89
Карма: 11
   поощрить/наказать


PostPosted: Thu Jan 20, 2005 5:06 pm (спустя 45 минут; написано за 15 минут 5 секунд)
   Post subject:
Reply with quote

Могу предпринять только симметричные ответные меры:
Евгений Галашин+2
tIT+1
:)

Спасибо.

PS карму надо повышать не мне, а разработчикам MySQL.
Back to top
View user's profile Send private message ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Thu Jan 20, 2005 6:57 pm (спустя 1 час 50 минут; написано за 2 минуты 38 секунд)
   Post subject:
Reply with quote

Bred Vilchec wrote:
`level` smallint(6) UNSIGNED NOT NULL DEFAULT '0',
Не пойму только, зачем Вам level. По идее, его всегда можно вычислить тем же SQL-запросом (см. конструкцию MySQL IF()).

И - еще один момент. Как Вы обходитесь без LEFT JOIN (или RIGHT JOIN)? Тот запрос, который Вы выше привели, по идее, работать не должен - ведь, например, в tbl5 не найдется соответствующего элемента (если максимальная вложенность в базе - 4), и будет возвращен пустой результат.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Thu Jan 20, 2005 7:42 pm (спустя 45 минут; написано за 17 секунд)
   Post subject:
Reply with quote

Дмитрий Кóтеров
А это просто другой вид JOIN`а
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Thu Jan 20, 2005 8:24 pm (спустя 41 минуту; написано за 29 секунд)
   Post subject:
Reply with quote

yUAC, спасибо. А и Б - это просто разные буквы алфавита. ;-)
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Vladimir Sergeev
Участник форума



Joined: 18 Feb 2004
Posts: 89
Карма: 11
   поощрить/наказать


PostPosted: Fri Jan 21, 2005 3:36 am (спустя 7 часов 12 минут; написано за 3 минуты 10 секунд)
   Post subject:
Reply with quote

Дмитрий Кóтеров wrote:
Тот запрос, который Вы выше привели, по идее, работать не должен - ведь, например, в tbl5 не найдется соответствующего элемента (если максимальная вложенность в базе - 4), и будет возвращен пустой результат.
Собственно вот за этим-то level и нужен.
Это, конечо, некоторая избыточность хранимых данных, но по сравнению с Nested Sets и
dbtree не такая уж и большая.
Back to top
View user's profile Send private message ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Fri Jan 21, 2005 7:16 pm (спустя 15 часов 39 минут; написано за 53 секунды)
   Post subject:
Reply with quote

Еще раз: очень вероятно, что при использовании LEFT JOIN-а никакой level не нужен.
Эх, сейчас попробую все-таки написать тестовый скрипт. Ждите.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Vladimir Sergeev
Участник форума



Joined: 18 Feb 2004
Posts: 89
Карма: 11
   поощрить/наказать


PostPosted: Fri Jan 21, 2005 8:14 pm (спустя 58 минут; написано за 9 минут 45 секунд)
   Post subject:
Reply with quote

Оки, теперь я понял Вашу идею.
Жду с нетерпением, особенно хотелось бы увидеть таинственный запрос с if'ами.
В принципе, если это сработает, это будет здорово, однако
в моем приложении level все же необходим.

Как я уже говорил, у меня 4 запроса:
первый получает level'ы
второй и третий связывают сами с собой таблицы юзеров и объектов
а вот четвертый, основной, связывает три таблицы и фактически выдает мне результат,
allow или denied.
Вся соль в том, что в ходе этого запроса мне необходимо "пробежать"
всех родителей пользоватлей (они получены 2-м запросом), начиная с корневого,
а также всех родителей объектов(они получены в 3-ем запросе), отсортировав их именно
по level.
Есть конечно кривой обходной путь - сортировать по id, мол у кого id меньше, тот и младше.
Но мне он тоже не подойдет, поскольку возможен перенос объекта или пользователя в другую ветку,
при этом, естественно, все такие "тонкие" связи нарушатся.
Back to top
View user's profile Send private message ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Fri Jan 21, 2005 10:23 pm (спустя 2 часа 8 минут; написано за 10 минут 22 секунды)
   Post subject:
Reply with quote

Собственно, все получилось. Вот скрипт:

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.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Fri Jan 21, 2005 10:25 pm (спустя 2 минуты; написано за 1 минуту 11 секунд)
   Post subject:
Reply with quote

Да, еще одно. Если "глубина копания" превышает фактическую глубину дерева, на быстродействие это отрицательным образом не сказывается. Иными словами, если у вас есть дерево с максимальной вложенностью 10, то можно делать запросы с вложенностью 30 - тормозить по сравнению с вложенностью 10 не будет.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Ant
Сотрудник «Лаборатории»



Joined: 17 Jun 2003
Posts: 6836
Карма: 127
   поощрить/наказать


PostPosted: Sat Jan 22, 2005 12:51 am (спустя 2 часа 25 минут; написано за 51 секунду)
   Post subject:
Reply with quote

Дмитрий Кóтеров wrote:
http://dbtree.dklab/search.php
«.ru» не забудьте добавить, кому надо попасть на страницу.
Back to top
View user's profile Send private message Send e-mail ICQ Number
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Goto page 1, 2, 3  Next
Page 1 of 3   
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
  XML