Я работаю над проектом, в котором мне нужно выполнить множество операций слияния подграфов с удаленным графом. Некоторые элементы подграфа могут уже существовать в удаленном графе. Я использую py2neo v3 и neo4j.
Я пытался использовать функции create
и merge
neo4j, и с обоими я получил удивительно плохие результаты. Еще более удивительным является то, что время, затрачиваемое на объединение подграфа, кажется квадратично растущим как с количеством узлов, так и с числом отношений! Когда подграф слишком большой, транзакция зависает. Одна вещь, которую я должен сказать, это то, что я проверил, и это не py2neo, который генерирует ряд зашифрованных утверждений, которые растут квадратично с размером подграфа. Поэтому, если что-то не так, это связано либо с тем, как я использую эти технологии, либо с реализацией neo4j. Я также попытался просмотреть планы запросов для запросов, сгенерированных py2neo, и не нашел в этом никакого ответа относительно того, почему времена запросов так сильно растут, но не верьте мне на слово, поскольку я относительно не инициирован.
Я с трудом мог найти какую-либо соответствующую информацию в Интернете, поэтому я попытался провести надлежащий сравнительный анализ, где сравнивал характеристики в зависимости от количества узлов и топологии подграфа, в зависимости от того, использую ли я операцию слияния или создания и использую ли я уникальные ограничения или нет. Ниже я привожу некоторые результаты, полученные мной для графиков с «линейной» топологией, что означает, что число отношений примерно совпадает с числом узлов (оно не растет квадратично).
В моем тесте я использую 5 различных типов меток для узлов и отношений, которые я назначаю случайным образом, и повторно использую 30% узлов, которые уже существуют в удаленном графе. Созданные мной узлы имеют только одно свойство, которое действует как идентификатор, и я сообщаю о производительности в зависимости от того, добавляю ли я уникальное ограничение на это свойство или нет. Все операции слияния выполняются в одной транзакции.
Время запросов для графов с линейной топологией в зависимости от количества узлов, используя функцию создания py2neo
![Query times for graphs with a linear topology in function of the number of nodes, using py2neo create function](https://i.stack.imgur.com/9Ox8p.png)
Время запросов для графов с линейной топологией в зависимости от числа узлов с использованием функции слияния py2neo
![Query times for graphs with a linear topology in function of the number of nodes, using py2neo merge function](https://i.stack.imgur.com/XT7Tw.png)
Как вы можете видеть, время, которое, по-видимому, увеличивается квадратично с количеством узлов (и отношений).
Вопрос, на который мне трудно ответить, состоит в том, делаю ли я что-то не так, или не делаю что-то, что должен, или это те представления, которые мы должны ожидать от neo4j для операций такого рода. Несмотря на это, кажется, что я мог бы решить эту проблему с производительностью, чтобы никогда не пытаться объединить большие подграфы сразу, а начать с объединения узлов за партией, а затем отношений. Это может и будет работать, но я хочу получить в конце, если у кого-то есть какие-либо рекомендации или идеи, чтобы поделиться.
Редактировать
Вот список суть, чтобы воспроизвести результаты выше, и другие.
https://gist.github.com/alreadytaikeune/6be006f0a338502524552a9765e79af6
Редактировать 2
После вопросов Майкла Голодера:
В коде, которым я поделился, я попытался написать средство форматирования для журналов neo4j.bolt, чтобы перехватывать запросы, отправляемые на сервер. Однако у меня нет систематического способа создания планов запросов для них.
Я не пробовал без докера и у меня нет SSD. Однако, учитывая размер, который я выделяю для jvm и размер обрабатываемого графа, все должно помещаться в оперативной памяти.
Я использую последний образ докера для neo4j, поэтому соответствующая версия выглядит как 3.3.5