За последние 24 часа нас посетили 18082 программиста и 1679 роботов. Сейчас ищут 1119 программистов ...

Вывод каталога с учетом иерархии из MySQL, Какие варианты?

Тема в разделе "MySQL", создана пользователем eurobax, 26 ноя 2009.

  1. eurobax

    eurobax Активный пользователь

    С нами с:
    25 ноя 2009
    Сообщения:
    8
    Симпатии:
    0
    Ищу лучшее решение по производительности/гибкости для MySQL. А задача такая:
    Есть каталог товаров

    1. Бытовая техника
    1.1. Телевизоры
    1.1.1.Плазменные
    1.1.1.1. LG
    1.1.1.1.1 LG 101
    1.1.1.1.2 LG 202
    1.1.1.1.3 LG 505
    1.1.1.2. Samsung
    1.1.1.2.1 Sam 1001
    1.1.1.2.2 Sam 2002
    1.1.1.2.3 Sam 5005
    и т.д.

    Коды типа "1.1.1.2.3" я привел для наглядности, я не храню их в записи, т.к. иерархия может быть бесконечная, а число элементов в группе может быть сотни тысяч.
    Условимся, Группа - это узел в котором есть вложенные элементы, а Элемент - это "лист"

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

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

    1. Nested Sets я уже рассмотрел, они не подходят под последнее условие. Даже не представляю как можно реально работать, если в каталог все время добавляют инфу о новых товарах к примеру. Пересчет всего дерева это ахтунг

    2. Есть еще вариант, когда храним все отношения между группами в отдельной таблице, там все отлично, все условия решаются одним запросом к БД. НО, иерархический вывод приходится делать скриптами (тоже один запрос, а потом рекуривная сортировка)

    Какие еще могут быть предложения?
     
  2. Clear

    Clear Активный пользователь

    С нами с:
    2 дек 2009
    Сообщения:
    4
    Симпатии:
    0
    Если вложенность не ограниченная, то без рекурсии вряд ли получится обойтись.
    А если вариант с рекурсией устраивает, то есть несколько вариантов решения:
    1. С помощью одной таблицы:
    - обязательный поля:
    id(int) - порядковый номер записи,
    parent_id(int) - для указания ID-номера родительской категории, по умолчанию 0,
    category (bool) - логический признак категория/товар.
    С добавлением все просто - надо только отслеживать ID родительской категории. Соответственно, если создаем корневую категорию товара (в примере, "Бытовая техника"), то parent_id=0.
    При изменении родительской категории для текущей подкатегории все товары автоматически переместятся.
    Удаление придется делать тоже, скорее всего, рекурсивно.

    2. С помощью 2 таблиц: категории и товары.
    По сути, это первый вариант, только с явным разделением категорий и товаров по разным таблицам БД. Это облегчит некоторые операции по управлению товарами, но придется строго следить за связью между таблицами.
     
  3. Phantik

    Phantik Активный пользователь

    С нами с:
    2 июл 2009
    Сообщения:
    163
    Симпатии:
    0
    для варианта с 1ой таблицей:
    А что если рекурсивное удаление переложить на обязанности оператора? Т.е. Хочет удалить узел, делается запрос на проверку дочерних элементов, если есть хоть 1 то сообщение типа "Не могу удалить т.к. каталог не пустой".

    Просто при рекурсивном удалении страшно представить будет сколько проверочных запросов будет выполняться. И вообще хватит ли памяти для больших объемов данных и большой разветвленности? Хотя конечно тип элемента, должен по идее упростить рекурсию.
     
  4. Clear

    Clear Активный пользователь

    С нами с:
    2 дек 2009
    Сообщения:
    4
    Симпатии:
    0
    А ваш оператор не повесится при наличии 1000+ элементов в текущем каталоге?
    Хорошо, если реализуете групповое удаление, а если по одной позиции?

    Не так уж и много... Как практика показывает, вложенность торговых каталогов ограничивается 5-7 уровнями. Если создана бОльшая вложенность, есть смысл задуматься о правильности выбора группировки.
    Даже при вложенности 5 уровня, в памяти будет висеть в один момент не больше 5 результатов запроса, т.к. после выполнения каждого уровня рекурсии память будет высвобождаться.

    Да и такие запросы будут проходить не в массовом порядке, а в исключительных случаях. Не будет же одновременно работать несколько 1000 операторов и чистить таким образом каталоги.

    Но в любом случае, надо тестировать. Я лишь предложил один из вариантов решения поставленной задачи, не углубляясь в анализ исключительных ситуаций, о которых имеете представление только Вы.
     
  5. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ