我有一个包含9537个节点和52846个关系的数据库。节点和关系都具有索引的属性。
我正在针对此数据库运行许多查询,这些查询或多或少具有以下形式:
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
答案 0 :(得分: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 :(得分: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;