我有一个过程,该过程针对Hive执行多个SQL语句,然后每个语句以周期性的提交样式遍历结果,并为每个10.000个结果打开一个事务。对于较小的量,过程将运行,但仅在处理所有语句时保留数据。在不限制数据的情况下,即使对于具有〜4.000.000结果的一条语句,该过程也会在〜1.500.000结果之后陷入困境,即使这些结果应该已经保留,也没有。
对于每个结果,检查是否已经存在对应的节点,如果不存在,则创建该节点并设置属性。因此,没有任何幻想。
我尝试通过Neo4j REST API而不是浏览器启动该过程,该浏览器适用于运行在3.3上的生产服务器,但适用于运行在3.5.9上的新测试服务器,即使这样做没有帮助,并且过程卡住了。 我还尝试了不同的负载,只是在一个测试过程中创建了数百万个节点(没有配置单元只是虚拟节点),这相当快,但是直到过程执行完之后,仍然没有保留更改。
由于apoc现在支持蜂巢,因此我使用apoc.load.jdbc和apoc.periodic.iterate将更简单的节点类型转换为CYPHER,这完全符合预期。但是由于时间限制,我无法将每种情况都转换为CYPHER。除了直接使用JAVA API外,还应该比cypher快。
所有神奇的事情都发生在以下方法中:
/**
* @param statement the prepared sql statement to be executed against hive
* @param label current node type
* @param filterId the indexed property on the given nodetype
* @return the custom node counter object that keeps track of the number of created and processed nodes
* @throws SQLException
*/
public NodeCounter writeDataInGraphDB(PreparedStatement statement, Label label, String filterId, GraphDatabaseService db, Log log) throws SQLException {
NodeCounter nc = new NodeCounter();
int commitSize = 10000;
ResultSet rs = statement.executeQuery();
while (rs.next()) {
int currentTransaction = 0;
boolean b = true;
try (Transaction tx = db.beginTx()) {
while (currentTransaction < commitSize && b) {
if (currentTransaction > 0) b = rs.next();
currentTransaction++;
nc.totalNodes++;
Node n = db.findNode(label, filterId, rs.getLong(filterId));
// Check if node exists
if (n == null) {
// Create new node
nc.newNodes++;
n = db.createNode(label);
setProperties(rs, n);
}
}
tx.success();
log.info("Transaction closed: New " + nc.newNodes + " Changed " + nc.changedNodes + " Total " + nc.totalNodes);
} catch (SQLException e) {
log.error(classname + methodname + "An error has occured", e);
}
}
rs.close();
log.info("Datasets: " + nc.totalNodes + " - New Nodes: " + nc.newNodes + " - Changed Nodes: " + nc.changedNodes);
return nc;
}
卡住的程序以越来越大的世界暂停消息的形式出现
Detected VM stop-the-world pause: {pauseTime=16115, gcTime=157, gcCount=1}
什么也没有发生,只会暂停更多的世界。
我希望使用事务能够持久化定期创建的节点,因为根据文档,一旦将事务标记为成功并关闭,事务就将其更改持久化(在我的情况下是通过自动关闭进行的) )。但是它们只保留一次(如果过程执行完)。
通过浏览器或REST API进行的调用周围是否存在某种隐藏的主事务,该事务仅在计算完所有内容后才保留更改?如此之多的结果要一口气保留下来,以至于Neo无法应对?