Neo4j - 缓慢的密码查询 - 带有层次结构的大图

时间:2014-10-20 10:05:51

标签: performance graph neo4j cypher

使用Neo4j 2.1.4。我有一张图表是' IS A'节点之间的关系(和其他类型的关系)。我在图中有一些层次结构(IS A关系),我需要知道一个层次结构的后代(IS A关系),它与第二层次结构的某个后代具有特定的已知关系。如果存在该特定已知关系,则返回第一层次结构的后代。

INPUTS:' ID_parentnode_hierarchy_01',' ID_relationship',' ID_parentnode_hierarchy_02'。
OUTPUT:' ID_parentnode_hierarchy_01'的后代(IS关系)具有“ID_relationship'与某些后代的“ID_parentnode_hierarchy_02'。

注意:该图表有500.000个节点和200万个关系。

我正在使用这个密码查询,但它非常慢(4GB RAM和3GHz Pentium双核64位PC中的aprox.40s)。可以构建更快的查询吗?

MATCH (parentnode_hierarchy_01: Node{nodeid : {ID_parentnode_hierarchy_01}})
WITH parentnode_hierarchy_01 
MATCH (parentnode_hierarchy_01) <- [:REL* {reltype: {isA}}] - (descendants01: Node)
WITH descendants01
MATCH (descendants01) - [:REL {reltype: {ID_relationship}}] -> (descendants02: Node)
WITH descendants02, descendants01
MATCH (parentnode_hierarchy_02: Node {nodeid: {ID_parentnode_hierarchy_02} }) 
<- [:REL* {reltype: {isA}}] - (descendants02)
RETURN DISTINCT descendants01;

非常感谢。

1 个答案:

答案 0 :(得分:1)

好吧,我可以稍微清理一下你的查询 - 这可能有助于我们更好地理解这些问题。我怀疑这个会运行得更快,但是使用清理后的版本我们可以讨论发生了什么:(主要是消除MATCH / WITH的不必要用途

MATCH (parent:Node {nodeid: {ID_parentnode_hierarchy_01}})<-[:REL* {reltype:{isA}}]-
      (descendants01:Node)-[:REL {reltype:{ID_relationship}}]->(descendants02:Node),

      (parent2:Node {nodeid: {ID_parentnode_hierarchy_02}})<-[:REL* {reltype:{isA}}]-
      (descendants02)
RETURN distinct descendants01;

这看起来像是从根开始搜索两个(可能是大的)树,树中某个地方的两个节点由{ID_relationship}链接。

除非您可以提供一些关于树中哪个节点可能具有ID_relationship或类似内容的查询提示,否则看起来您最终可能会比较两棵树中的每两个节点。所以这看起来可能需要n * k时间,其中n是第一棵树中的节点数,k是第二棵树中的节点数。

以下是一些需要考虑的策略 - 您应该使用哪些策略取决于您的数据:

  1. 树中是否有一些深度可能会找到这些链接?你能在[:REL* {reltype:{isA}}]
  2. 的深度上加上一个范围
  3. 您可以向descendants01descendants02添加哪些其他条件?是否有任何可以帮助使查询更具选择性的内容,以便您不会将一个树中的每个节点与另一个树中的每个节点进行比较?
  4. 你可能尝试的另一个策略是:(这可能是一个可怕的想法,但它值得尝试) - 基本上寻找从一个根到另一个的路径,在任何数量的无向边缘isa类型,或其他。您的数据模型与:REL属性具有reltype个关系。这可能是反模式;而不是reltype属性,为什么关系类型不仅仅是那个?这可以防止我想要的查询在下面写入:

    MATCH p=shortestPath((p1:Node {nodeid: {first_parent_id}})-[:isA|ID_relationship*]-(p2:Node {nodeid: {second_parent_id}}))
    return p;
    

    这将返回一个&#34; root&#34;通过您想要的桥梁到另一个。然后,您可以使用路径函数来提取所需的节点。请注意,由于您的数据模型,此查询目前无法实现。