LINUX.ORG.RU

Дерево и листья. Структура базы.


0

1

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

Есть дерево, содержащее группы текстовых записей. Дерево построено по принципу Nested Sets. Дерево может быть, например, таким:

Корень
  Новости
    Новости на русском
    Новости на английском
    Новости на немецком
  Правила
    Краткое описание
      Что
      Где
      Когда
    Терминология
    Резюме
  Статьи
    Статьи на русском
      О проекте
    Статьи на английском
    Статьи на немецком

Каждую группу записей назовем, для простоты, веткой. База данных, содержащее данное дерево пусть называется tree.

У каждой ветки есть конечные записи - листья. Листья - это текстовые записи. Они лежат в другой базе - leaves. Они содержат заголовок, текст записи, время создания, время правки, автора, прочую информацию.


Вопрос. Как правильно связать листья и дерево? У меня два варианта:

1. Простой. В базе leaves добавить поле branch_id, которое будет указывать, какой ветке принадлежит запись.

2. Сложный. Создать еще одну базу со структурой один-ко-многим, в которой будет прописана связь branch_id -> leave_id. Ну, то есть в этой дополнительно базе будет указано, какой ветке какие записи принадлежат.

Какой вариант правильнее?

Как-то сложно. Проще не различать ветки и листья и запихнуть все в одну таблицу leaves. В таблице leaves, соответственно, добавить поле parent_leaf_id. А в алгоритме отображения прописать, что доп. свойства выводить у листа только в том случае, если у него нет дочерних листов например. Или если поле is_final_leaf установлено в true. Так будет проще листья с развитием структуры превращать в ветки.

ovk48 ★★★ ()
Ответ на: комментарий от ovk48

> Как-то сложно. Проще не различать ветки и листья и запихнуть все в одну таблицу leaves. В таблице leaves, соответственно, добавить поле parent_leaf_id. А в алгоритме отображения прописать, что доп. свойства выводить у листа только в том случае, если у него нет дочерних листов например. Или если поле is_final_leaf установлено в true. Так будет проще листья с развитием структуры превращать в ветки.

Так, понятно. Проектированием баз данных вы еще больше меня не занимались.

webhamster ()
Ответ на: комментарий от webhamster

>Так, понятно. Проектированием баз данных вы еще больше меня не занимались.

Я проектированием БД занимался и занимаюсь и считаю данное решение весьма удобным и гибким. Id и parent_id определяют иерархию, любые другие поля - данные. Другое дело, если ты хочешь иметь разный набор данных для веток и для листьев, но в приведенном тобой примере этого нет.

staseg ★★★★★ ()
Ответ на: комментарий от webhamster

а совет imho не такой уже и плохой. всё равно slq одномерный, как не крути. но, подождём гуру этого дела.

beastie ★★★★★ ()

Зависит от условий задачи и вложенностей

ИМХО, на первом уровне я бы делал ноды, связывая их по суррогатному ключу с листьями, далее бы делал пункт 1, то есть начиная со второго уровня листьев реализовывал бы parent->child

Но тут многое зависит от задачи, повторюсь

westtrd ()

>1. Простой. В базе leaves добавить поле branch_id, которое будет указывать, какой ветке принадлежит запись.

Вполне.

2. Сложный. Создать еще одну базу со структурой один-ко-многим, в которой будет прописана связь branch_id -> leave_id. Ну, то есть в этой дополнительно базе будет указано, какой ветке какие записи принадлежат.

Если у тебя один лист не может быть в двух ветках, то зачем вообще городить m2m?

anonymous ()
Ответ на: комментарий от staseg

> Я проектированием БД занимался и занимаюсь и считаю данное решение весьма удобным и гибким. Id и parent_id определяют иерархию, любые другие поля - данные. Другое дело, если ты хочешь иметь разный набор данных для веток и для листьев, но в приведенном тобой примере этого нет.

Конечно, разный набор данных для веток и листьев.

Меня интересует вот что. Если сделать по варианту 1, то выборку нужно будет делать из большой базы (база с листьями - большая по объему в мегабайтах). То есть, в большой базе нужно будет находить листья с указанным parent_id.

Если вынести эту связку в отдельную базу, то выборка будет происходить на микроскопической базе в которой всего-то два поля. А затем получив список записей, можно будет уже целенаправленно извлекать их из базы с листьями.

Вот я и думаю, будет ли второй способ меньше нагружать MySQL-базу чем первый способ?


webhamster ()
Ответ на: комментарий от webhamster

Вот я и думаю, будет ли второй способ меньше нагружать MySQL-базу чем первый способ?

imho нет. чисто логически: что там, что там тебе нужно выбрать n из мульёна. только во втором случае у тебя две таблицы.

а ля псевдокод:

SELECT * FROM leaves INNER JOIN tree ON leaves.parent == tree.id;

верзус

SELECT * FROM leaves WHERE parent == 'id';

хотя, тут тестить надо

beastie ★★★★★ ()
Ответ на: комментарий от beastie

bugfix: к первому ещё надо добавить WHERE или что-то такое.

beastie ★★★★★ ()
Ответ на: комментарий от webhamster

большая по объему в мегабайтах

а это вообще ещё копейки. KISS!

beastie ★★★★★ ()
Ответ на: комментарий от webhamster

> Конечно, разный набор данных для веток и листьев.

И чем же кардинально отличаются ветка «Новости» и лист «Новости на русском»?

ovk48 ★★★ ()
Ответ на: комментарий от ovk48

И чем же кардинально отличаются ветка «Новости» и лист «Новости на русском»?

«Новости на русском» - это ветка. В топике приведен пример дерева групп.

Ветка содержит обычно только заголовок, подзаголовок, текстовое описание, сопроводительную картинку.

Лист содержит заголовок, текст записи, время создания, время правки, автора, прочую информацию.

webhamster ()
Ответ на: комментарий от webhamster

Просто так с отступами всё расписано, чисто тебе XML.

Это было такое лаконичное предложение. :)

//Слежу за развитием темы с интересом. Кстати вот для настоящих индейцев ссылка: http://dba.stackexchange.com/

Hoodoo ★★★★★ ()

nested sets же и использовать

легко гуглится

anonymous ()
Ответ на: комментарий от webhamster

Тривиально решается задача ваша.

Имеем таблицы:

TREEPOS(ID,PARENT_ID) - определяет иерархию и вложенность.

LEAF=(ID,TREEPOS_ID,<дополнительные поля для листьев>) - определяет содержимое листьев

NODE=(ID,TREEPOS_ID,<дополнительные поля для серединных узлов>) - определяет содержимое серединных узлов

Если появится необходимость заиметь разные типы листьев, то делаем это так:

LEAF=(ID, TREEPOS_ID)

LEAF_SIMPLE=(LEAF_ID,<поля для простых листьев>)

LEAF_COMPLEX=(LEAF_ID,<поля для сложных листьев>)

Проблема производительности пусть вас не очень волнует пока не встретили реальные а не предполагаемые затыки.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.