Является ли отображение объектов Python, которое я делаю для neo4j, слишком наивным?

1

Я ищу некоторые общие рекомендации о том, как переписать код приложения, чтобы быть не наивным, или отказаться от neo4j для другой модели хранения данных. Это не только "субъективно", поскольку оно в значительной степени относится к конкретному правильному использованию драйвера neo4j в Python и к тому, как он работает с моим кодом.

Фон:

Моя команда и я используем neo4j для хранения данных, совместимых с графикой, которые первоначально хранятся в объектах Python. Первоначально нам советовал локальный эксперт использовать neo4j, поскольку он, по-видимому, соответствовал нашим требованиям по хранению данных и манипулированию/запросам. Данные всегда являются конкретными примерами набора тщательно построенных онтологий. Например (псевдоданные):

Superclass1 -contains-> SubclassA
Superclass1 -implements->SubclassB
Superclass1 -isAssociatedWith-> Superclass2
SubclassB -hasColor-> Color1
Color1 -hasLabel-> string::"Red"

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

Для прототипирования мы хранили эти данные как последовательности грамматических троек (subject-> глагол /predicate-> объект) с использованием RDFLib и с использованием графического генератора RDFLib для построения графика.

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

Чтобы постоянно хранить эти объекты и, надеюсь, ускорить запись и чтение (запрос/фильтрацию) этих данных, мы создали собственный код сопоставления объектов, который использует официальный драйвер python neo4j для записи и чтения этих объектов Python рекурсивно/из базы данных neo4j.

Эта проблема:

Для больших и сложных наборов данных (например, узлы 15k+ и 15k+) часть реляционного сопоставления объекта (ORM) нашего кода является слишком медленной и плохо масштабируется. Но ни я, ни мой коллега не являются экспертами в базах данных или neo4j. Я думаю, что мы наивно относимся к тому, как выполнить эту ORM. Мы начали задаваться вопросом, имеет ли смысл использовать neo4j, когда более традиционные ORM (например, SQL Alchemy) могут быть лучшим выбором.

Например, алгоритм фиксации ORM, который мы имеем сейчас, является рекурсивной функцией, которая совершает такой объект (псевдокод):

def commit(object):
    for childstr in object:             # For each child object
        child = getattr(object, childstr)   # Get the actual object

        if attribute is <our object base type): # Open transaction, make nodes and relationship
            with session.begin_transaction() as tx:
                <construct Cypher query with:
                MERGE object            (make object node)
                MERGE child             (make its child node)
                MERGE object-[]->child  (create relation)
                >
                tx.run(<All 3 merges>)

            commit(child)                   # Recursively write the child and its children to neo4j

Неужели это так наивно? Будет ли лучше доступна OGM-библиотека, такая как Py2neo OGM, несмотря на то, что мы настроены? Я видел этот и подобные вопросы, которые рекомендуют тот или иной метод OGM, но в этой статье говорится, что вообще не использовать OGM.

Должны ли мы реально реализовать каждый метод и ориентир производительности? Похоже, что должны быть некоторые лучшие практики (кроме использования пакетного IMPORT, который не подходит для наших случаев использования). И мы читали статьи, подобные тем, которые были связаны, и видели различные советы по написанию более качественных запросов, но лучше отступить назад и изучить ситуацию в целом, прежде чем пытаться оптимизировать код по строкам. Хотя ясно, что мы можем в некоторой степени улучшить алгоритм ORM.

Имеет ли смысл писать и читать большие, глубокие иерархические объекты в/из neo4j, используя такую рекурсивную стратегию? Есть ли что-то в Cypher или драйверах neo4j, которых нам не хватает? Или лучше использовать что-то вроде Py2neo OGM? Лучше всего просто отказаться от neo4j? Преимущества neo4j и Cypher трудно игнорировать, и наши данные, похоже, хорошо вписываются в график. Благодарю.

Теги:
database
neo4j
cypher

2 ответа

1

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

Я бы предложил для первоначального импорта, где вы создаете каждый класс/объект, вместо того, чтобы просто добавлять новое или редактировать отношения для одного класса, чтобы вы использовали своих инспекторов классов для простого создания графического представления данных и затем используйте Cypher для его создания в гораздо меньшем количестве транзакций в Neo4J. Используя некоторую базовую теорию топологических графов, вы можете ее оптимизировать, уменьшив количество поисковых запросов, которые вам нужно сделать.

Вы можете создать NetworkX MultiDiGraph в коде python для моделирования структуры ваших классов. С этого момента существует несколько разных стратегий по размещению данных в Neo4J - я также просто нашел это, но понятия не имею, работает ли он или насколько он эффективен.

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

1. Создайте график в двух наборах запросов

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

2. Начиная с топологически самой высокой или самой низкой точки графика, создайте граф как серию путей

Если у вас много разных меток UNWIND и меток узлов, это может быть связано с написанием много логики шифрования, объединяющей UNWIND и FOREACH (CASE r.label = 'SomeLabel' THEN [1] ELSE [] | CREATE (n:SomeLabel {node_unique_id: x})->, но если граф очень иерархичен, вы также можете использовать python для отслеживания того, какие узлы имеют все свои нижние узлы и созданные ранее отношения, а затем использовать эти знания для ограничения размера путей, которые отправляются в Neo4J в запрос.

3. Используйте APOC для импорта всего графика

Другой вариант, который может или не может соответствовать вашему варианту использования и может или не может быть более эффективным, - это экспортировать граф в GraphML с помощью NetworkX, а затем использовать инструмент импорта APOC GraphML.

Опять же, трудно предложить точное решение, не видя всех ваших данных, но я надеюсь, что это несколько полезно в качестве руля в правильном направлении! Рад помочь/ответить на любые другие вопросы, основанные на большем количестве данных.

  • 0
    Обновлено, чтобы добавить новое возможное решение с использованием GraphML
  • 1
    Спасибо за это. Наши данные действительно довольно иерархичны, и кажется, что вы говорите, что лучше всего попытаться оптимизировать ORM, который я уже сделал. Насколько затратны множественные транзакции по сравнению с крупными транзакциями с невероятно длинными строками запроса? Похоже, прямо сейчас, построение плоской ORM будет означать выполнение последнего.
Показать ещё 2 комментария
0

Здесь многое происходит, поэтому я постараюсь решить это в более мелких вопросах

Будет ли лучше доступна OGM-библиотека, такая как Py2neo OGM

С любой библиотекой ORM/OGM реальность такова, что вы всегда можете добиться лучшей производительности, минуя их и вникая в живот зверя. Тем не менее, это не все ORMs. ORM предназначен для того, чтобы сэкономить ваше время и усилия, сделав относительно эффективное использование БД простым.

Таким образом, это зависит, если вы хотите получить лучшую производительность, пропустите ORM и потратите свое время на работу как можно ниже уровня (* Требуется передовое знание низкого уровня зверя, с которым вы работаете, и много времени). В противном случае, как правило, лучше всего использовать библиотеку ORM.

Наш код слишком медленный и плохо масштабируется

Базы данных сложны. Если это вообще возможно, я бы рекомендовал принести кого-то на борту, чтобы быть администратором/экспертом по всей базе данных. (Это сложнее, когда у вас еще нет одного, чтобы проверять новых нанимателей, которые действительно знают, о чем они говорят)

Предполагая, что это не вариант, рассмотрим некоторые вещи.

  • IO стоит дорого. Особенно по сети. Минимизируйте данные, которые необходимо отправить в любом направлении. (Вот почему вы возвращаете результаты страницы. Возвращайте только те данные, которые вам нужны, поскольку вам это действительно нужно)
    • Предостережение об этом, создание соединений с запросами очень дорого. Минимизируйте вызовы в БД. (Веселитесь, балансируя два ^ _ ^) (Примечание: ORM обычно имеют встроенную механику, чтобы только совершить то, что изменилось)
  • Получите данные, которые вы хотите быстро. Создавайте индексы в базе данных, чтобы значительно улучшить скорость выборки. Чем более уникальный и последовательный идентификатор, тем лучше.
    • Caveat, индексы должны быть обновлены в отношении записей, которые изменяют значение в них. Таким образом, индексы уменьшают скорость записи и потребляют больше памяти, чтобы получить скорость чтения. Минимизировать индексы.
  • Транзакции - операция памяти. Завершение транзакции - операция ввода-вывода на диске. Вот почему пакетные задания намного эффективнее.
    • Предостережение, память не бесконечна. Держите свои рабочие места в разумных размерах.

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

Для прототипирования мы хранили эти данные как последовательности грамматических троек

Меньше вопрос, и больше выражение, но разные типы баз данных имеют разные сильные и слабые стороны. Бункеры без схемы больше специализированы для хранилищ кешей; Графические БД специализированы для запросов на основе отношений (ребер); Реляционные БД специализированы для сбора/обновления записей (таблиц); И Triplestores более специализированы для, ну, троек (RDF); (например, есть больше типов)

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

Должны ли мы реально реализовать каждый метод и ориентир производительности?

Ну, это часть того, почему хранимые процедуры так важны. ORM помогают абстрагировать эту часть, и наличие эксперта в домене действительно поможет. Это может быть просто то, что вы подталкиваете пределы того, что может сделать одна машина. Возможно, вам просто нужно перейти на кластер; или, возможно, у вас есть ужасные недостатки кода, которые вы касаетесь узла 10k раз в 1 операции сохранения, когда значение (или 1) не изменилось. Если честно, настольная маркировка не делает много, если вы не знаете, что ищете. Например, обычно разница между 5 и 0,5 секундами может быть такой же простой, как создание 1 индекса.

(Чтобы быть справедливым, при покупке больших и лучших серверов/кластеров баз данных может оказаться неэффективным решением, иногда это наиболее экономически выгодно по сравнению с зарплатой 1 администратора базы данных. Так что, опять же, это зависит от ваших приоритетов. И я уверен ваш босс, вероятно, будет расставлять приоритеты по-другому, чем вы хотите)


TL; DR

Вы должны нанять эксперта по домену, чтобы помочь вам.

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

Если у вас нет на это времени, возможно, единственной спасительной изюминкой будет просто модернизировать ваше оборудование, чтобы решить проблему с помощью грубой силы. (* Пока рост не экспоненциальный)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню