Neo4j 数据加载性能:驱动程序与自定义过程
Neo4j data loading performance: driver vs custom procedure
我正在从 Neo4j Java 自定义过程切换到基于 Neo4j Java 驱动程序的方法。我想以某种微服务 运行 我的图形算法结束,而不是通过 Cypher 调用自定义过程。我使用一堆标准的 HashMaps 实现了遍历:一旦数据从 Neo4j 加载到这些 HashMaps,图形遍历比我原来的自定义过程快得多,所以这是非常有前途的。
现在回答我的问题:在自定义过程中,我能够像这样将图形(40 个 mio 边,10 个 mio 节点)加载到哈希图中:
@Context
public GraphDatabaseService db;
...
HashMap<Long, Long> mapNodeIdProperty = new HashMap<>();
db.beginTx().getAllNodes().stream().forEach((org.neo4j.graphdb.Node n)
-> mapNodeIdProperty.put(n.getId(),
(Long) n.getProperty("combProp")));
这大约需要一分钟,我认为这是可以接受的服务启动时间。
现在,我能找到的使用驱动程序的最佳解决方案如下:
driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ) );
...
try ( Session session = driver.session() )
{
String status = session.writeTransaction( new TransactionWork<String>()
{
@Override
public String execute( Transaction tx )
{
Stream<Record> resultStream = (Stream<Record>) tx.run(
"MATCH (n) RETURN n").stream();
resultStream.forEach((Record n) -> listNodes.add(((Record) n).get("n").asNode()));
return "ok; length=" + listNodes.size();
}
});
System.out.println( status);
}
这会花费太多时间,即使我使用密码查询将返回的节点数限制在几千个也是如此。我从来没有等到完整的图表加载。
与存储过程相比,使用驱动程序(或替代方法)获得相同速度的最佳选择是什么?是否有基本的限制会抑制这一点?
请记住,过程代码在服务器本身上执行,它有效地嵌入了 Neo4j。
将其与通过网络传输所有节点及其属性的需要进行比较。这是程序不需要的很多额外 I/O。
正如 InverseFalcon 指出的那样,通过 bolt 协议进行的传输具有速度限制,在程序中不存在。我正在寻找的是 here 描述的嵌入式 DBMS。我现在这样使用:
public class GraphAccess implements AutoCloseable
{
...
private final DatabaseManagementService managementService =
new DatabaseManagementServiceBuilder(NEO4J_DATA_PATH)
.setConfig( GraphDatabaseSettings.read_only, true )
.setConfig(GraphDatabaseSettings.logs_directory,
NEO4J_LOGS_DIRECTORY).build();
public final GraphDatabaseService db = managementService.database( NEO4J_DATABASE_NAME );
public final HashMap<Integer, String> mapNodeProp = new HashMap<>();
...
private void getNodeData() {
try ( Transaction tx = db.beginTx() ) {
tx.getAllNodes().forEach((Node n) -> {
final Integer nodeId = (int) n.getId();
mapNodeProp.put(nodeId, (String) n.getProperty("name"));
}
}
}
}
这具有高吞吐量的优势(因为它不使用驱动程序,而是直接访问 neo4j 数据库数据)并且可以在 Spring 应用程序的上下文中使用它(因为它是未作为自定义过程实施)。
我正在从 Neo4j Java 自定义过程切换到基于 Neo4j Java 驱动程序的方法。我想以某种微服务 运行 我的图形算法结束,而不是通过 Cypher 调用自定义过程。我使用一堆标准的 HashMaps 实现了遍历:一旦数据从 Neo4j 加载到这些 HashMaps,图形遍历比我原来的自定义过程快得多,所以这是非常有前途的。
现在回答我的问题:在自定义过程中,我能够像这样将图形(40 个 mio 边,10 个 mio 节点)加载到哈希图中:
@Context
public GraphDatabaseService db;
...
HashMap<Long, Long> mapNodeIdProperty = new HashMap<>();
db.beginTx().getAllNodes().stream().forEach((org.neo4j.graphdb.Node n)
-> mapNodeIdProperty.put(n.getId(),
(Long) n.getProperty("combProp")));
这大约需要一分钟,我认为这是可以接受的服务启动时间。
现在,我能找到的使用驱动程序的最佳解决方案如下:
driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ) );
...
try ( Session session = driver.session() )
{
String status = session.writeTransaction( new TransactionWork<String>()
{
@Override
public String execute( Transaction tx )
{
Stream<Record> resultStream = (Stream<Record>) tx.run(
"MATCH (n) RETURN n").stream();
resultStream.forEach((Record n) -> listNodes.add(((Record) n).get("n").asNode()));
return "ok; length=" + listNodes.size();
}
});
System.out.println( status);
}
这会花费太多时间,即使我使用密码查询将返回的节点数限制在几千个也是如此。我从来没有等到完整的图表加载。
与存储过程相比,使用驱动程序(或替代方法)获得相同速度的最佳选择是什么?是否有基本的限制会抑制这一点?
请记住,过程代码在服务器本身上执行,它有效地嵌入了 Neo4j。
将其与通过网络传输所有节点及其属性的需要进行比较。这是程序不需要的很多额外 I/O。
正如 InverseFalcon 指出的那样,通过 bolt 协议进行的传输具有速度限制,在程序中不存在。我正在寻找的是 here 描述的嵌入式 DBMS。我现在这样使用:
public class GraphAccess implements AutoCloseable
{
...
private final DatabaseManagementService managementService =
new DatabaseManagementServiceBuilder(NEO4J_DATA_PATH)
.setConfig( GraphDatabaseSettings.read_only, true )
.setConfig(GraphDatabaseSettings.logs_directory,
NEO4J_LOGS_DIRECTORY).build();
public final GraphDatabaseService db = managementService.database( NEO4J_DATABASE_NAME );
public final HashMap<Integer, String> mapNodeProp = new HashMap<>();
...
private void getNodeData() {
try ( Transaction tx = db.beginTx() ) {
tx.getAllNodes().forEach((Node n) -> {
final Integer nodeId = (int) n.getId();
mapNodeProp.put(nodeId, (String) n.getProperty("name"));
}
}
}
}
这具有高吞吐量的优势(因为它不使用驱动程序,而是直接访问 neo4j 数据库数据)并且可以在 Spring 应用程序的上下文中使用它(因为它是未作为自定义过程实施)。