Как мне хранить иерархические данные, не относящиеся к дереву (то есть любой общий граф)? - PullRequest
1 голос
/ 24 июня 2010

У меня есть сайт, написанный на PHP. В настоящее время он использует MySQL для всех нужд своей базы данных (я открыт для дополнительных технологий БД).

Содержание системы взаимосвязано. Эти отношения могут быть представлены в виде графа, где вершины являются частями контента, а ребра - отношениями. Мне нужно иметь возможность пройти этот график. В частности мне нужно уметь:

  • Получить количество детей на заданной глубине (например, сколько внуков имеет предмет)
  • Получить совокупное количество детей на заданной глубине (например, сколько детей и внуков имеет предмет)
  • Получить максимальную глубину для данного корня (например, какой самый длинный путь из этого элемента)
  • Получить детей на заданной глубине (например, кто внуки этого предмета)
  • Получить родителей на заданной глубине (например, кто является бабушкой и дедушкой этого элемента)
  • Посмотрите, какие статусы (такие как «скрытый» или «заблокированный») были унаследованы от родителей.

Поскольку это график в динамической системе, а не дерево или традиционная иерархия, есть некоторые сложности, которые, как мне кажется, исключают обычные трюки на основе SQL (например, список смежности и перечисление пути).

Основные тонкости:

  • Контент может иметь более одного ребенка.

  • Контент может иметь более одного родителя.

  • График отношений элемента может отличаться для каждого пользователя. Например, определенный контент может быть скрыт для одного человека, но не для другого.

  • Элементы могут появляться более одного раза в дереве графиков и могут появляться с разной длиной пути (например, элемент 50 может быть непосредственным дочерним элементом, а также дочерним элементом 3-го поколения).

  • Графики могут содержать сотни тысяч элементов.

Некоторые дополнительные сложности:

  • Различные типы контента могут быть связаны (например, опрос может быть связан с сообщением на форуме, или пользователь может быть связан с сообществом)

  • Существует несколько различных типов отношений (например, отношения между родителями и детьми, отношения собственности, отношения между сверстниками)

  • В зависимости от типа отношений, разрешения и ограничения могут передаваться или не передаваться от родителя к потомку (например, если родитель скрыт, дочерний объект также будет скрыт, но если скрытый элемент скрыт, статус не передается)

Мои наивные (медленные) "решения"

В настоящее время я использую наивный подход с использованием SQL. У меня есть одна таблица «Отношения» с этими столбцами:

item1ID (int)
item1TypeID (int)
item2ID (int)
item2TypeID (int)
relationshipTypeID (int)

В PHP я динамически генерирую запросы, полные внутренних самообъединений, чтобы найти максимальную глубину, а затем, когда это выясняется, я генерирую один запрос, который пересекает иерархию и извлекает всю необходимую информацию. Это уже слишком медленно, даже при правильной индексации.

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

Мой вопрос

Должен быть лучший способ. Что это? Я знаю, что на StackOverflow уже есть много вопросов и ответов, касающихся проблемы иерархической информации в SQL, но это не совсем иерархия - это полноценный график.

Поскольку у меня есть сильные модели, я могу смешать другую технологию БД, чтобы обрабатывать аспекты отношений, не разрушая существующую базу кода. Я изучал NoSQL-решения, но практически ничего о них не знаю. Я также слышал о «Графических базах данных» (таких как Neo4J), которые, исходя из названия и различных слайдов PowerPoint, которые я видел, звучат именно так, как мне нужно. Тем не менее, я не знаю, какие из них на самом деле достаточно устойчивы, или какие из них будут хорошо работать с PHP.

Помоги мне, StackOverflow, ты моя единственная надежда.

1 Ответ

1 голос
/ 25 июня 2010

Из вашего описания, Neo4j действительно должен очень хорошо соответствовать тем проблемам, с которыми вы сталкиваетесь.Например, поддержка типов отношений должна оказаться здесь полезной.Существует активное сообщество , которое увеличивает шансы этого GraphDB выжить в будущем.Он также был в производстве в течение долгого времени.

PHP-сторона Neo4j не настолько блестящая, но я думаю, что REST API открываетсядля некоторых интересных сценариев.Разрабатывается PHP REST клиент (краткое введение здесь ).Затем эксперимент с мостом PHP / Java (я сам не пробовал).

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

Что касается СУБД, я боролся с подобными проблемами в PHP / MySQL на основесистема.Использование хранимых процедур помогло относительно структурирования проекта, но на самом деле производительность немного ухудшилась (это было в то время, когда хранимые процедуры были новой функцией в MySQL).По моему опыту, PostgreSQL лучше справляется со сложными запросами, но написание реальных графовых запросов для него не представляется возможным (см. здесь и здесь , почему это так!)

Отказ от ответственности: я являюсь частью команды Neo4j

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...