【问题标题】:Performance in Neo4jNeo4j 中的性能
【发布时间】:2014-01-30 09:14:11
【问题描述】:

我有一个包含 2.217.731 个节点和 3.127.475 个关系的数据库,其中节点是不同的设备,它们之间的关系类似于“CONNECTED_TO”、“IS_INSIDE”等。

我正在尝试遍历图形以查找特定节点。在 Cypher 中它看起来像

    MATCH (n:Equipment)<-[IS_INSIDE*]-()<-[CONNECTED_TO*]-(m:Cable) where n.name = "name" RETURN m

使用 Java Core API,据我所知,这应该是查询 Neo4j 最快的方法,需要几秒钟,但它运行了几十分钟。

我正在使用 neo4j-2.0.0 和 java 版本“1.7.0_45”,最大 Java 堆大小 7 gigs

Neo4j 属性:

    Map<String, String> config = new HashMap<>();

    config.put( "neostore.nodestore.db.mapped_memory", "1800M" );
    config.put( "neostore.relationshipstore.db.mapped_memory", "3G" );
    config.put( "neostore.propertystore.db.mapped_memory", "100M" );
    config.put( "neostore.propertystore.db.strings.mapped_memory", "150M" );
    config.put( "neostore.propertystore.db.arrays.mapped_memory", "10M" );

    inserter = BatchInserters.inserter("target/graphDb", config);

我是 Neo4j 的新手,不知道如何调整它以获得更好的性能。

【问题讨论】:

  • 你能上传你的图表吗?
  • 每个级别有多少个节点?例如,有多少个 IS_INSIDE 链接到 n.name?几根电缆?

标签: java performance neo4j


【解决方案1】:

如果您必须遍历整个图表,那么这将很慢。如果这是一个常见查询,请考虑在 Equiptment.name 上创建一个索引,这在 neo4j 2.0.0 里程碑中是可能的。然后它只会在索引中查找匹配的名称(基本上是哈希表),然后检查匹配节点周围的模式——这将非常快。见http://blog.neo4j.org/2013/12/neo4j-20-ga-graphs-for-everyone.html

【讨论】:

  • 是的,这个查询将被大量使用。我做了一些算法改进,避免检查具有相同端节点的路径,并且访问节点的数量显着减少,现在它运行约 20 秒。但是索引并没有帮助我。我使用 BatchInserterIndexProvider。除了 Equipment.name 上的索引之外,我还在 CONNECTED_TO 关系属性 fromport 和 toport 上放置了索引。通过查看数据库文件,我可以看到建立了索引,但时间没有改变。
【解决方案2】:

请在设备节点的属性上为名称创建一个索引。

CREATE INDEX ON :Equipment(name)

那么请尝试以下优化查询。

MATCH (n:Equipment { name: "name" }),
      (n)<-[IS_INSIDE*]-(x),
      (x)<-[CONNECTED_TO*]-(m:Cable)
RETURN m

请注意,这与您指定的匹配是等效的,但它会将其分成三组,这会导致 Neo4j 上的查询执行计划首先匹配属性名称上的 n:Equipment 节点,而不是绘制图表全局匹配操作。从减少的n:Equipment 节点集合中,以下匹配语句将更高效地扫描IS_INSIDECONNECTED_TO 的可变长度模式。

【讨论】:

  • 感谢您的回答,我不知道这个。但是在我描述的情况下,它对我没有帮助,因为我不使用 cypher 来查询 Neo4j,我使用 Java 核心 api。我只是认为通过编写等效的密码查询来解释我想要做什么会更容易。无论如何,谢谢,它将来对我有用。
【解决方案3】:

首先要意识到,在 GraphDB 中,性能主要取决于您构建的模型类型和各种节点的基数(在您的情况下为设备和电缆)。 通常使用 PROFILE 和 EXPLAIN 查询将导致有关查询性能的信息性洞察,即查询的数据库命中次数和所需时间。选择基于较少 DB 命中数的查询是有利的。

有了这个,让我们先看看你正在使用的查询:

MATCH (n:Equipment)<-[IS_INSIDE*]-()<-[CONNECTED_TO*]-(m:Cable) 
where n.name = "name" 
RETURN m

对此有几点建议:

1) 当您尝试查找位于特定设备节点内的设备节点时,您不会提及节点标签。 尝试使用:

MATCH (n:Equipment)<-[IS_INSIDE*]-(:Equipment)

代替

MATCH (n:Equipment)<-[IS_INSIDE*]-()

因为在您的情况下,您在设备和电缆节点中都搜索名称为“名称”的设备。使用我提到的替代方案,它将仅限于 Cable 节点。假设设备不能在电缆内。

2) 正如其他人所提到的,在设备和电缆节点之上构建索引会有所帮助。 在 Equipment.name 属性上建立索引。 您可以在所有电缆属性上构建索引,这可能会进一步提高性能。

你也可以分享一下有多少个设备节点,有多少个电缆节点。 另外我假设您已经确保设备节点和电缆节点是不同的。拥有更多的关系是可以的,但我们的模型通常可以从更少的节点匹配中受益。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    相关资源
    最近更新 更多