2013-05-22 5 views
0

У меня есть база данных с 9537 узлами и 52846 взаимосвязью. Оба узла и отношения имеют атрибуты, которые индексируются.Как я могу оптимизировать вложенный запрос Cypher?

Я бег много запросов к этой базе данных, которые имеют более или менее следующую форму:

START n0 = node:my_nodes(label='2'), n4 = node:my_nodes(label='2') 
MATCH n0-[r0]-n4 
WITH n0, n4, r0    
MATCH n0-[r1]-n3     
WHERE r1.lab - r0.lab = 0 and n3.label = 0 and id(r1) <> id(r0) 
WITH n0, n4, n3, r0, r1     
MATCH n0-[r2]-n2 
WHERE r2.lab - r0.lab = 0 and n2.label = 2 and id(r2) <> id(r0) and id(r2) <> id(r1) 
WITH n0, n4, n3, n2, r0, r1, r2      
MATCH n0-[r3]-n1 
WHERE r3.lab - r0.lab = -1 and n1.label= 0 and id(r3) <> id(r0) and id(r3) <> id(r1) and id(r3) <> id(r2)  
RETURN id(n0), r0.lab, r1.lab, r2.lab, r3.lab; 

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

Моя проблема прямо сейчас в том, что если java не попадает в пределы памяти, запрос запускается более 30 минут.

Есть ли способ оптимизировать этот запрос? Нужно ли настраивать некоторые параметры конфигурации для повышения производительности?

PS: Я использую neo4j-1.9-RC2 на FreeBSD (там работает дистрибутив Linux). Конфигурация Памяти:

wrapper.java.initmemory=512 
wrapper.java.maxmemory=8192 

ответ

1

Удалите WITH положение и объединить MATCH эсов и WHERE S вместе.

START n0 = node:my_nodes(label='2'), n4 = node:my_nodes(label='2') 
MATCH n0-[r0]-n4 
    , n0-[r1]-n3 
    , n0-[r2]-n2 
    , n0-[r3]-n1 
WHERE r1.lab - r0.lab = 0 and n3.label = 0 and id(r1) <> id(r0) 
    AND r2.lab - r0.lab = 0 and n2.label = 2 and id(r2) <> id(r0) and id(r2) <> id(r1) 
    AND r3.lab - r0.lab = -1 and n1.label= 0 and id(r3) <> id(r0) and id(r3) <> id(r1) and id(r3) <> id(r2) 
RETURN id(n0), r0.lab, r1.lab, r2.lab, r3.lab; 

Проблема с использованием WITH является то, что она заставляет Neo4j перечислить все возможные результаты, прежде чем продолжить на будущие условия. Например, в вашем запросе выше neo4j найдет ВСЕ возможные пути, включая n0-[r0]-n4, перечислить каждый из них, а затем передать результаты на следующий шаг. На следующем шаге будут найдены все подходящие кандидаты, перечислите их все и передайте их и т. Д.

Объединив эти статьи вместе, не разделяя их на WITH, neo4j может оценивать результаты по мере их прохождения и короткого замыкания раньше.

+1

Я думал, что это было как WITH работал, но я уверен, что это на самом деле ленив, а это означает, что это больше похоже на трубопровод, который посылает приводит весь путь к end, пока окончательный возврат не будет повторен (если вам не нужно сортировать или делать что-то еще, что делает невозможным). Однако короткозамкнутая часть вашего аргумента остается в силе. –

+0

WITH ленив, что он не предварительно вычисляет вещи, кроме случаев, когда вы используете 'order by',' distinct' или aggregation –

+0

, ранее я писал запросы cypher так, как предлагает @ ean5533, но я понял, что запросы с 'WITH' выполнять быстрее. Сейчас я попробую разные комбинации. Имеет ли значение, сколько узлов я помещаю в «СТАРТ»? Лучше ли ставить только 'n0' в' START', а остальные - в 'WHERE'? – npobedina

1

Чего-то на самом деле хотите достичь?

Опишите адрес своего домена?

Обновление до 1.9.GA

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

Попытайтесь использовать команду profile.

Кроме того, возможно, вместо передачи r0 и т.п. возможно только перейдите r0.lab as r0_lab, нормальный для id.

Было бы хорошо иметь доступный набор данных где-то, чтобы выполнить профилирование.

Вы также можете выполнить отдельные части и подсчитать количество строк, чтобы увидеть, сколько строк возвращено (комбинаторный взрыв), тогда имеет смысл использовать WITH distinct ...., чтобы объединить промежуточные результаты в меньшее количество строк.

Возможно попробовать это для начала:

START n0 = node:my_nodes(label='2'), n4 = node:my_nodes(label='2') 
MATCH n0-[r0]-n4 
WITH n0, r0.lab as r0_lab, id(r0) as id_r0 
MATCH n0-[r1]-n3     
WHERE r1.lab = r0_lab and n3.label = 0 and id(r1) <> r0_id 
WITH n0, r0_lab, r1.lab as r1_lab, [r0_id,id(r1)] as rel_ids 
MATCH n0-[r2]-n2 
WHERE r2.lab = r0_lab and n2.label = 2 and id(r2) NOT IN rel_ids 
WITH n0, rel_ids + id(r2) as rel_ids,r1_lab,r1_lab,r2.lab as r2_lab 
MATCH n0-[r3]-n1 
WHERE r3.lab = r0_lab - 1 and n1.label= 0 and id(r3) NOT IN rel_ids 
RETURN id(n0), r0_lab, r1_lab, r2_lab, r3.lab; 
+0

спасибо за хорошие идеи. пока ваше предложение, особенно с использованием 'distinct', работает лучше всего. Я действительно занимаюсь разработкой диаграммы графа, и у меня есть семейство шаблонов, для которых мне нужно перечислить вложения графов. Таким образом, этот конкретный шаблон является лишь одним из возможных. Но я заметил, что это тот, который занимает больше всего времени для запроса. С образцами пути Neo4j справляется довольно хорошо. – npobedina

+0

Что вы подразумеваете под «Cypher тянет туда, где выражения в шаблонный шаблон, поэтому убедитесь, что они видны совпадению, которое вы хотите ограничить выражениями». ? как я могу убедиться, что Cypher «видит» выражения where? – npobedina

Смежные вопросы