2013-05-22 95 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:我在FreeBSD上使用neo4j-1.9-RC2(linux发行版在那里运行)。 内存配置:

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

回答

1

取出WITH条款,并结合您的MATCH ES和WHEREš在一起。

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

我认为这是与如何工作,但我敢肯定它实际上是懒惰的,这意味着它更像是一个管道发送结果一路走过来的结束,直到最终的回归迭代完成(除非你需要排序,或者做一些使其不可能的事情)。不过,你的论点的短路部分仍然有效。 –

+0

WITH是懒惰它不预先计算的东西,除非当你使用'order by','distinct'或聚合 –

+0

以前我正在写密码查询的方式@ ean5533建议,但我想通过'WITH'查询表现更快。我会尝试现在不同的组合。这与我在“START”中放入多少个节点有关系吗?把'n0'放在'START'里,其余的放在'WHERE'里过滤出来会更好吗? – npobedina

1

zou实际上想实现什么?

你能描述你的域名吗?

升级到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'看到'在哪里表达? – npobedina