Обработка данных иерархии в базе данных - PullRequest
7 голосов
/ 25 февраля 2009

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

Таблица узлов

NodeId int PRIMARY KEY
NodeParentId int NULL
DisplaySeq int NOT NULL
Title nvarchar(255)

Таблица предков

NodeId int
AncestorId int
Hops int

с индексами на NodeId, AncestorId, Hops

Таблицы выглядят так:

Таблица узлов

NodeId    NodeParentId    DisplaySeq    Title
1         NULL            1             'Root'
2         1               1             'Child 1'
3         1               2             'Child 2'
4         2               1             'Grandchild 1'
5         2               2             'Grandchild 2'

Таблица предков

NodeId    AncestorId    Hops
1         NULL          0
1         1             0
2         1             1
2         2             0
3         1             1
3         3             0
4         1             2
4         2             1
4         4             0
5         1             2
5         2             1
5         5             0

С этим дизайном я обнаружил, что с большими иерархиями я могу очень быстро получить весь раздел иерархии, подключившись к таблице Ancestor для AncestorId = target NodeId, например:

SELECT *
FROM Node n
INNER JOIN Ancestor a on a.NodeId=n.NodeId
WHERE a.AncestorId = @TargetNodeId

Также легко получить прямых детей

SELECT *
FROM Node n
INNER JOIN Ancestor a on a.NodeId=n.NodeId
WHERE a.AncestorId = @TargetNodeId
AND Hops = 1

Мне интересно знать, какие другие решения вы могли бы использовать для такого типа вещей. По моему опыту, иерархии могут стать довольно волосатыми, и любой способ оптимизации их поиска очень важен.

Ответы [ 6 ]

10 голосов
/ 25 февраля 2009

Для этого есть некоторые специфичные для вендора расширения, но мой любимый дб-нейтральный способ исходит от Джо Селко - Google 'Деревья и иерархии Джо Селко' или купить эту книгу: текст ссылки

Это очень умный способ, основанный на множествах. Простая в запросе иерархия. Я добавил поле 'parentID', которое у вас есть, только потому, что я часто задаю вопросы 'direct children' и 'parent', и это ускоряет их. Но это прекрасный способ получить запрос «предков» или «потомков».

6 голосов
/ 25 февраля 2009

Вы также можете проверить шаблон «вложенные множества»:

http://www.intelligententerprise.com/001020/celko.jhtml (Неработающая ссылка)

Или вы можете Google для более.

P.S .: Проклятия, n8wrl , вы печатаете быстрее, чем я!

4 голосов
/ 25 февраля 2009

Как уже отмечали MarkusQ и n8wrl, у Джо Селко есть кое-что хорошее по этому поводу. Я просто добавлю, что существует несколько способов моделирования иерархии (я считаю, что в книге Джо есть несколько, а не один, который он считает «лучшим»). Мы надеемся, что ваше окончательное решение будет учитывать ваши конкретные потребности. Некоторые из различных способов моделирования лучше для операций с интенсивной записью, в то время как другие лучше для частого или быстрого чтения вверх и вниз по иерархии. Просто имейте в виду, что ваша система будет делать с этим.

2 голосов
/ 25 февраля 2009

SQL Server 2008 представил тип данных иерархический

1 голос
/ 25 февраля 2009

Я бы определенно рекомендовал вложенные наборы. Они великолепны.

http://threebit.net/tutorials/nestedset/tutorial1.html http://www.dbmsmag.com/9603d06.html

1 голос
/ 25 февраля 2009

В Oracle вы можете использовать CONNECT BY / START WITH для запроса иерархических данных. В SQL Server вы можете использовать хранимую процедуру, которая вызывает себя рекурсивно.

...