создание 200K отношений с узлом занимает много времени в Neo4J 3.5? - PullRequest
0 голосов
/ 04 июля 2019

У меня есть одна такая вершина

Vertex1

{
    name:'hello',
    id: '2',
    key: '12345',
    col1: 'value1',
    col2: 'value2',
    .......
}

Vertex2, Vertex3, ..... Vertex200K

{
    name:'hello',
    id: '1',
    key: '12345',
    col1: 'value1',
    col2: 'value2',
    .......
}

Cypher Query

MATCH (a:Dense1) where a.id <> "1" 
WITH a 
MATCH (b:Dense1) where b.id = "1" 
WITH a,b 
WHERE a.key = b.key 
MERGE (a)-[:PARENT_OF]->(b)

Конечный результат должен быть Vertex1 должен иметь степень 200K , следовательно,должно быть 200К отношений.Тем не менее, приведенный выше запрос занимает много времени, в значительной степени убивая пропускную способность до 500 в секунду.Любые идеи о том, как создать отношения / ребра быстрее?

Когда я запускаю профиль и запрос шифра выше, он продолжает работать вечно и не возвращается, поэтому я уменьшил размер с 200 КБ до 20 КБ, и вот чтопрофиль показывает меня.

enter image description here

Ответы [ 3 ]

1 голос
/ 06 июля 2019

Учитывая ваши ограничения памяти и высокие удары по БД, связанные с вашим MERGE отношений, проблема, вероятно, заключается в том, что вы пытаетесь MERGE 200k отношений в одной транзакции. Вероятно, вам следует выполнить пакетную обработку, используя apoc.periodic.iterate () из Процедуры APOC :

CALL apoc.periodic.iterate("
MATCH (a:Dense1) 
WHERE a.id <> '1'
MATCH (b:Dense1) 
WHERE b.id = '1' AND a.key = b.key 
RETURN a, b",
"MERGE (a)-[:PARENT_OF]->(b)",
{}) YIELD batches, total, errorMessages
RETURN batches, total, errorMessages 

Это должно объединить эти слияния по 10 тыс. За раз.

Кроме того, если вам точно известно, что эти отношения еще не существуют, используйте CREATE вместо MERGE, это будет быстрее.

0 голосов
/ 09 июля 2019

Можете ли вы попробовать запустить

MATCH (b:Dense1) where b.id <> "1" 
WITH b, b.key AS bKey
MATCH (a:Dense1) where a.id = "1" AND a.key = bKey 
MERGE (a)-[:PARENT_OF]->(b)

, убедившись, что у вас есть индексы для идентификатора и ключа?

Кроме того, правильно ли я понимаю, что id НЕ уникален, и у вас есть 1 узел с id = 2 и 200k с id = 1?Если я ошибся, переверните условие, чтобы первая строка возвращала один узел, в который вы хотите добавить все отношения, а во вторую часть - все остальные 200 тыс. Узлов.Кроме того, в слиянии, поместите узел с низкой плотностью в качестве первого (так что здесь, b получит 200k отношений) - если это не так, измените его на (b) <- [: XXX] - (a). </p>

Прошло много времени с тех пор, как я имел дело с большими импортами / слияниями, но я вспоминаю, что извлекал переменную явно (например, bKey), которую затем можно сопоставить в индексе, и начиная с отдельных узлов (одного илипереход на более высокие (несколько a) несколько лучше, чем запросы с предложениями where, похожими на a.key = b.key.

Сказав, что 200k отношений в одной транзакции, И соединены с однойnode, это много, так как простое сопоставление по индексу быстро находит узлы, но все же вам нужно проверить все исходящие отношения, чтобы увидеть, случайно ли они уже ссылаются на другой узел.Итак, к тому времени, когда вы создаете свои последние отношения, вам нужно выполнить итерацию / проверку почти 200 тыс. Отношений.

Один трюк - запуск пакетов в цикле до тех пор, пока ничего не будет создано, например,

MATCH (b:Dense1) where b.id = "1" 
WITH b, b.key AS bKey
MATCH (a:Dense1) where a.id <> "1" AND a.key = bKey 
AND NOT (a) -[:PARENT_OF]-> (b) WITH a,b LIMIT 10000
MERGE (a)-[:PARENT_OF]->(b)

Это может показать вам, вероятно, что чем дальше пакет, тем дольше он занимает смысл - логически логично, так как все больше и больше связей из b необходимо проверять по мере продвижения.

Или, как показано в других ответах, пакетная обработка через APOC.

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

0 голосов
/ 04 июля 2019

Создайте индекс для свойств, которые вы используете для сопоставления.

Здесь id и key свойства.

Вы можете создать индекс с помощьюследующие запросы:

CREATE INDEX ON :Schema1(id);
CREATE INDEX ON :Schema1(key);

Это первый шаг к повышению производительности.Вы можете улучшить свои навыки с помощью нескольких других приемов.

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