Обработка данных иерархии в базе данных
Мне любопытно узнать, как лучше всего (наилучшая практика) обрабатывать иерархии в отношении дизайна базы данных. Вот небольшой пример того, как я обычно с ними справляюсь.
Таблица узлов
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)6
Как уже отметили MarkusQ и n8wrl, у Джо Селко есть кое-что по этому поводу. Я просто добавлю, что существует несколько способов моделирования иерархии (я считаю, что книга Джо содержит несколько, а не только один, который он считает «лучшим»). Надеемся, что ваше окончательное решение будет учитывать ваши собственные потребности. Некоторые из различных способов моделирования лучше подходят для операций с интенсивной записью, в то время как другие лучше для частого или быстрого чтения вверх и вниз по иерархии. Просто имейте в виду, что ваша система будет с этим делать.
В SQL Server 2008 появился тип данных hierarchyid.
Вы также можете проверить шаблон «вложенные наборы»:
http://www.intelligententerprise.com/001020/celko.jhtml (неработающая ссылка)
Или вы можете найти в Google больше.
Для этого есть несколько расширений, зависящих от поставщика, но мой любимый способ, не зависящий от базы данных, исходит от Джо Селко - загуглите «Деревья и иерархии Джо Селко» или купите эту книгу: текст ссылки
Это очень умный подход, основанный на множестве вещей. Легко запрашивать иерархию. Я добавил поле «parentID», которое у вас есть, только потому, что я часто задаю вопросы «прямым потомкам» и «родителям», и это ускоряет их. Но это прекрасный способ получить запрос «происхождение» или «описание».
Я определенно рекомендую вложенные наборы. Они великолепны.
http://threebit.net/tutorials/nestedset/tutorial1.html http://www.dbmsmag.com/9603d06.html