Эффективное назначение UUID для подключенных компонентов в Neo4j - PullRequest
0 голосов
/ 15 октября 2018

Я разделил мой график на ~ 400 000 подключенных компонентов, используя функцию algo.unionFind из библиотеки Neo4j Graph Algorithms.

Каждый узел n в одном и том же подключенном компоненте имеет одинаковое значение n.partition.Однако теперь я хочу назначить каждому подключенному компоненту UUID, чтобы у каждого узла n в подключенном компоненте был n.uuid, заполненный компонентом UUID.Каков наиболее эффективный способ сделать это?

В настоящее время я получаю список всех значений n.partition, а затем прохожу каждый раздел и запускаю запрос Cypher, чтобы обновить все узлы этого раздела для получения сгенерированного UUID.Я использую оболочку Python py2neo, и этот процесс довольно медленный.

Edit:

Запросы Cypher, которые я сейчас использую:

MATCH (n)
RETURN DISTINCT n.partition AS partition

, чтобы получитьсписок идентификаторов разделов и затем итеративный вызов:

MATCH (n)
WHERE n.partition = <PARTITION_ID>
SET n.uuid = <GENERATED_UUID>

для каждого из идентификаторов разделов.

Редактировать 2: я могу получить ~ 180k / 400k подключенных компонентов, используяследующий запрос:

CALL apoc.periodic.iterate(
"MATCH (n)
WITH n.partition as partition, COLLECT(n) as nodes
RETURN partition, nodes, apoc.create.uuid() as uuid",
"FOREACH (n in nodes | SET n.uuid = uuid)",
{batchSize:1000, parallel:true}
)

до получения ошибки кучи: "neo4j.exceptions.ClientError: Failed to invoke procedure `apoc.periodic.iterate`: Caused by: java.lang.OutOfMemoryError: Java heap space"

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

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

MATCH (n)
// WHERE exists(n.partition) // only if there are nodes in the graph without partitions
WITH n.partition as partition, collect(n) as nodes
WITH partition, nodes, randomUUID() as uuid
FOREACH (n in nodes | SET n.uuid = uuid)

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

0 голосов
/ 15 октября 2018

Лучше всего было бы установить плагин APOC для Neo4j, чтобы вы могли использовать функцию UUID apoc.create.uuid() в Cypher.(чтобы его можно было сгенерировать и назначить в одной и той же транзакции)

Чтобы создать 1 uuid на раздел, вам потребуется использовать WITH для хранения uuid во временной переменной.Он будет выполняться для каждой строки, поэтому вам нужно сделать это, как только у вас будет один раздел

USING PERIODIC COMMIT 5000 // commit every 5k changes
MATCH (n)
WITH DISTINCT n.partition as p // will exclude null
WITH p, apoc.create.uuid() as uuid // create reusable uuid
// now just match and assign
MATCH (n)
WHERE n.partition = p
SET n.uuid = uuid

или, как предложил InverseFalcon

MATCH (n)
WHERE exists(n.partition) // to filter out nulls
WITH n.partition as p, collect(n) as nodes // collect nodes so each row is 1 partition, and it's nodes
WITH p, nodes, apoc.create.uuid() as uuid // create reusable uuid
FOREACH (n in nodes | SET n.uuid = uuid) // assign uuid to each node in collection

Первый запрос более удобен для периодической фиксации, посколькуему не нужно загружать все в память, чтобы начать выполнять задания.Однако без оператора perodic commit он, в конечном счете, загрузит все в память, поскольку он должен удерживать его для журнала транзакций.Как только он достигает точки фиксации, он может очистить журнал транзакций, чтобы уменьшить использование памяти.

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

...