Хорошие обзоры
Вообще говоря, вы принимаете решение между временем быстрого чтения (например, вложенным множеством) или временем быстрой записи (список смежности). Обычно вы получаете комбинацию из приведенных ниже вариантов, которые лучше всего соответствуют вашим потребностям. Следующее обеспечивает некоторое углубленное чтение:
- Еще одно сравнение вложенных интервалов и списка смежности : лучшее сравнение списка смежности, материализованного пути, вложенного набора и вложенного интервала, которое я нашел.
- Модели для иерархических данных : слайды с хорошими объяснениями компромиссов и примера использования
- Представление иерархий в MySQL : очень хороший обзор Nested Set, в частности
- Иерархические данные в РСУБД : наиболее полный и хорошо организованный набор ссылок, которые я когда-либо видел, но не так много для объяснения
Опции
Я знаю и общие черты:
- Список смежности :
- Столбцы: ID, ParentID
- Легко реализовать.
- Дешевый узел перемещается, вставляется и удаляется.
- Дорого, чтобы найти уровень, происхождение и потомков, путь
- Избегайте N + 1 с помощью общих табличных выражений в базах данных, которые их поддерживают
- Вложенный набор (он же модифицированный обход дерева предзаказа )
- Столбцы: слева, справа
- Дешевое происхождение, потомки
- Очень дорогие
O(n/2)
перемещения, вставки, удаления из-за нестабильной кодировки
- Таблица мостов (также называемая таблицами закрытия / триггерами )
- Использует отдельную таблицу соединений с: предком, потомком, глубиной (необязательно)
- Дешевое происхождение и потомки
- Записывает затраты
O(log n)
(размер поддерева) для вставки, обновления, удаления - Нормализованное кодирование: хорошо для статистики СУБД и планировщика запросов в соединениях
- Требуется несколько строк на узел
- Столбец Lineage (он же Материализованный путь , Перечисление пути)
- Колонка: происхождение (например, / parent / child / внук / etc ...)
- Дешевые потомки с помощью префиксного запроса (например
LEFT(lineage, #) = '/enumerated/path'
) - Записывает затраты
O(log n)
(размер поддерева) для вставки, обновления, удаления - Нереляционный: использует тип данных Array или сериализованный формат строки
- Вложенные интервалы
- Как и вложенный набор, но с реальным / float / decimal, чтобы кодирование не было изменчивым (недорогое перемещение / вставка / удаление)
- Имеет проблемы с реальным / плавающим / десятичным представлением / точностью
- Вариант матричного кодирования добавляет кодирование предка (материализованный путь) для «свободного», но с добавленной хитростью линейной алгебры.
- Плоский стол
- Модифицированный список смежности, который добавляет столбец уровня и ранга (например, упорядочение) к каждой записи.
- Дешево перебирать / разбивать на страницы
- Дорого переместить и удалить
- Полезное использование: обсуждение темы - форумы / комментарии блога
- Несколько столбцов линии
- Столбцы: по одному для каждого уровня происхождения, относятся ко всем родителям вплоть до корня, уровни ниже уровня элемента установлены в NULL.
- Дешевые предки, потомки, уровень
- Дешевая вставка, удаление, перемещение листьев
- Дорогая вставка, удаление, перемещение внутренних узлов
- Жесткий предел того, насколько глубокой может быть иерархия
Примечания к базе данных
MySQL
оракул
- Используйте CONNECT BY для прохождения списков смежности
PostgreSQL
- Тип данных дерева для Материализованного Пути
SQL Server
- Общее резюме
- 2008 предлагает тип данных HierarchyId , который помогает с подходом Lineage Column и расширяет глубину, которую можно представить.
Closure Tables
превосходятAdjacency List
,Path Enumeration
иNested Sets
с точки зрения простоты использования (и я предполагаю , что производительность, а).