Cypher - зависание запросов с неограниченной длиной пути и большой длиной пути - PullRequest
0 голосов
/ 07 мая 2020

Я использую Neo4j Community 4.0.4.
Я столкнулся с этой проблемой, используя официальный драйвер Bolt для Python, но он также полностью воспроизводится в браузере Neo4j (версия 4.0.7).

На данный момент у меня есть очень простой график, состоящий из следующих типов узлов и отношений:

(:Document)-[:contains]->(:Block)
(:Block)<-[:prev]-(:Block)-[:next]->(:Block)

На данный момент во всей моей тестовой базе данных всего 75 узлов - 1 узел документа и 74 Блокировать узлы.

Выполнение следующего оператора Cypher доводит ЦП до 100%, и использование памяти неограниченно возрастает, после чего я должен завершить сеанс:

match (d:Doc{name: 'doc name'}) 
optional match (d)-[*]-(n) 
return d,n

I также в какой-то момент получил ошибку размера кучи Java. Он начинает работать только в том случае, если я устанавливаю строгую верхнюю границу отношения или указываю направление, например:

optional match (d)-[*..5]->(n)

Например, это уже не работает (ответ занимает вечность, поэтому я должен убить session):

optional match (d)-[*..5]-(n)

Учитывая, что (a) я выполняю строго локальный обход графа, в котором должны быть исключительно хорошие базы данных графов, (b) кластеры, связанные с разными начальными узлами, НЕ подключены и ( c) мой набор тестовых данных крошечный, как это может происходить?

Судя по симптомам, движок просто не отслеживает, какие узлы и отношения уже были посещены при подготовке результаты ... или мне что-то не хватает?

ОБНОВЛЕНИЕ:

На это только что ответил на форуме сообщества Neo4j сотрудник Neo4j: https://community.neo4j.com/t/getting-paths-of-any-length-or-long-paths-does-not-work/18298

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

Было предложено решение на основе APO C:

match (d:Doc{name: 'doc name'}) 
CALL apoc.path.subgraphNodes(d, {}) YIELD node as n
return d, n

В моем случае я отключил подграфы, состоящие из десятков тысяч узлы каждый и относительно плотны. Это произошло при попытке удалить узел (: Do c) и все, что с ним связано, перед повторной загрузкой новой версии подграфа в Neo4j:

disconnect delete d, n

I рассматривайте эту задачу «удаление старой версии перед повторной загрузкой» как очень распространенную рабочую задачу для подграфов, которые могут быть у многих людей в их сценариях использования ... Установка и управление дополнительными библиотеками (такими как APO C или Graph Библиотека Data Science) кажется излишним для чего-то столь простого ... Но либо это, либо более целенаправленное удаление.

1 Ответ

2 голосов
/ 07 мая 2020
Предложение

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

Главное, что следует учитывать, это то, что шаблоны отношений переменной длины имеют экспоненциальную сложность (время и память). Если проходимые узлы имеют в среднем R релевантных отношений, то предложение MATCH должно проходить примерно R**P возможных путей длиной P. Чем выше значение P (особенно без верхней границы), тем хуже становится. Но высокий R тоже вредит.

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