缩放Neo4J以进行同步写入/合并查询

时间:2014-04-02 16:39:50

标签: java neo4j

使用NodeJS,我将这些数据收集到Neo4J:

  • user(id,login)
  • app(id,title)
  • 机器(身份证,地址)

这完全是异步的。 这意味着很多次我可以获得有关数据库中存在的用户和APP的信息。

因此,只需创建项目然后再创建CREATE关系,我需要在USER和APP中为每一行运行MERGE以确保它们在数据库中。在此之后,我可以建立关系。

我发送到/cypher端点。

params:{props:objects_array},
query:[
  ' FOREACH (p IN {props} | ',
  '   MERGE (u:user    {id:p._user_id})    SET u.id = p._user_id ',
  '   MERGE (a:app     {id:p._app_id})     SET a.id = p._app_id ',
  '   MERGE (m:machine {id:p._machine_id}) SET m.id = p._machine_id ',
  '   MERGE (u)-[:OPENED]->(a) ',
  '   MERGE (a)-[:USERS]->(u) ',
  '   MERGE (u)-[:WORK_IN]->(m) ',
  ' )',
].join("")

这很有效,但速度很慢。 我通过更改每个请求的同时请求和行来控制余额。

同时有5个请求,每个500行,它可以解决4个死锁错误,需要2分钟才能完成5000行。

问题是它一直需要2核CPU到99%(digitalocean 4gb RAM),我需要将其扩展到150个并发请求,而不仅仅是5个。

我认为可能的解决方案是:

  • 垂直扩展到四核(现在解决,不是长时间的解决方案)
  • 分发操作的数据库副本(这可能吗?)
  • 某种方式使用CREATE而不是MERGE。这是非常快的,但我需要确保唯一的ID和不同的属性。也许使用约束?
  • neo4j真的能够处理这么多数据吗?

2 个答案:

答案 0 :(得分:3)

如果您只使用没有唯一约束或索引的MERGE,则需要Neo4j为每个MERGE执行节点空间的完整扫描,以验证给定属性不存在其他项目。这意味着您最终会得到一个非常高的算法复杂度,并且还会受到磁盘限制。

您需要为应该在数据库中唯一的标签/属性元组创建索引或(最好)唯一约束。这应该会显着加快您的MERGE查询速度。

此外,如果您使用新的事务端点(http://docs.neo4j.org/chunked/stable/rest-api-transactional.html)来替换密码端点,那么您会感觉更好。它支持与cypher端点相同的功能,但提高了性能,并且能够为每个HTTP调用运行多个cypher语句,并允许事务在服务器上保持运行,以便为客户端提供长期运行的事务支持。

过去,Neo4j 2.1将在未来几个月内发布,它包含几项性能增强功能,可显着加快并发查询的执行速度。您可能想尝试即将到来的里程碑,看看它对您的表现有何帮助。

答案 1 :(得分:0)

我不知道cypher但是使用neo4j rest api你可以使用batch insertion轻松实现这一点,你也可以在同一批处理中同时创建关系,并在批处理中的后续作业中创建节点。 refer to items created earlier