我正在尝试使用graphrepository在spring-neo4j中创建一个应用程序。 其中一个要求是在两个子节点之间找到最低公共祖先(lca)。
目前我使用以下查询来实现此目的:
@Query("MATCH path = (c1:Concept)-[r:Relation*{type: 'Is a'}]->(ca:Concept)<-[r:Relation*{type: 'Is a'}]-(c2:Concept)
WHERE c1.conceptID = {conceptId1} AND c2.conceptID = {conceptId2}
RETURN ca ORDER BY length(path) LIMIT 1")
Concept findLowestCommonAncestor(@Param("conceptId1") Long conceptId1, @Param("conceptId2") Long conceptId2);
这里的问题是性能。最初我的图表由330 000个节点和2 000 000个关系组成。我感兴趣的关系是类型:“是一个”。它们仅在树中向上移动(将子节点与父节点连接)。最大向上距离为3。
这是树结构:
因为我有几个像这样的树结构,所以我决定添加一个将所有不同树结构连接在一起的根节点。这样lca总能找到。但添加此根节点大大改变了我的性能: 从558毫秒到562286毫秒
我知道添加根节点会影响性能,但不应该这么多,对吧?如果是这样,有没有更好的方法来计算lca?
我认为我的密码查询只会在树中向上查找节点。因此,在这种情况下,添加额外的根节点不应该对性能产生太大影响。
答案 0 :(得分:1)
首先,我要感谢@Supamiu对我提问的帮助。
虽然他的答案对某些案件来说可能已经足够了。在我的情况下,实际上不可能改变模型。
令人惊讶的是,我设法通过更改密码查询来提高性能。
我的原始查询:
MATCH path = (c1:Concept)-[r1:Relation*{type: "Is a"}]->(ca:Concept)<-[r2:Relation*{type: "Is a"}]-(c2:Concept)
WHERE c1.conceptID=35104066 AND c2.conceptID=35808913
RETURN ca
ORDER BY length(path)
LIMIT 1
个人资料:http://i.imgur.com/14yleCo.png
我把它改为:
MATCH (c1:Concept {conceptID: 35104066})-[:Relation*{type: "Is a"}]->(p1:Concept)
MATCH (:Concept {conceptID: 35808913})-[:Relation*{type: "Is a"}]->(p2:Concept)
WHERE p1.conceptID = p2.conceptID
MATCH path = (c1)-[:Relation*{type: "Is a"}]->(p1)
RETURN p1
ORDER BY length(path)
LIMIT 1
这使我的最低共同祖先在100毫秒左右,显着改善!
我仍然不完全理解为什么会产生这样的差异。但我认为其中一个原因是我使用的是树形结构。我想在第二个查询中,Cypher只在树中向上搜索,导致搜索关系减少。因此,在blob结构中,我认为这不会有所帮助。
有人可以证实这一点吗?
答案 1 :(得分:0)
你的问题是一个关系标签问题,让我解释一下:
首先,您的请求与:Relation
关系中的无限深度相匹配。
您说数据库中的每个树现在都与根节点相关,我猜它与使用:Relation
关系的根节点相关。
因此,当您将标记为:Relation
的每个关系与无限深度匹配时,它将匹配数据库中的每个关系,然后在type
属性上进行过滤。这就是为什么这个根节点添加了这样一个perf问题,因为它以相同的关系连接每个节点。
如何解决这个问题?
更改关系标签,使用它们而不是与属性匹配:
(ca:Concept{properties...})-[:IS_A]->(ca2:Concept)
使用另一个关系标签将您的顶级树节点链接到根节点。
然后,当您使用无限深度请求匹配您的节点时,您将能够使用标签进行匹配,从而避免您实际遇到的问题。
另一个解决方案是在查询中添加深度最大值,因为您的树最多为3个级别,您可以将关系深度限制为3.但在我看来,第一种解决方案更好,因为只创建一种类型在neo4j中,使用属性进行关系和过滤是一种不好的做法。
所以,这是您的第一个个人资料:http://i.imgur.com/xskg39J.png
你可以在这里看到匹配[:Relation*]
在被过滤之前有31,328次点击,这非常好。
在第二个配置文件(带根节点)上:http://i.imgur.com/14yleCo.png
你可以看到相同的匹配得到近2,000,000次点击,经过过滤后,是500,000次......这太过分了。
我认为解决方案是Path,你可以看看这个:
只有&#34;更好的&#34;才能解决问题。密码查询。我认为您的问题可以通过更好的数据模型来解决,但是如果没有项目本身的工作,很难找到哪个问题。我能提供的唯一想法是指南:http://neo4j.com/developer/guide-data-modeling/