我目前正在评估neo4j在图中插入大量节点/关系。它不是关于批量插入可以实现的初始插入。它是关于在运行时期间在嵌入模式下使用neo4j的java应用程序中频繁处理的插入(当前版本为1.8.1,因为它随spring-data-neo4j 2.2.2.RELEASE一起提供)。
这些插入通常是遵循星型模式的节点。一个节点(导入数据集的根节点)最多包含 1000000(一百万!)个子节点。子节点通常也与其他附加节点有关系。但到目前为止,这些测试还没有涵盖这些关系。 总体目标是最多五分钟导入大量数据!
为了模拟这种插入,我编写了一个小的junit测试,它使用Neo4jTemplate
来创建节点和关系。每个插入的叶子都有一个关键字,以便以后处理:
@Test
@Transactional
@Rollback
public void generateUngroupedNode()
{
long numberOfLeafs = 1000000;
Assert.assertTrue(this.template.transactionIsRunning());
Node root = this.template.createNode(map(NAME, UNGROUPED));
String groupingKey = null;
for (long index = 0; index < numberOfLeafs; index++)
{
// Just a sample division of leafs to possible groups
// Creates keys to be grouped by to groups containing 2 leafs each
if (index % 2 == 0)
{
groupingKey = UUID.randomUUID().toString();
}
Node leaf = this.template.createNode(map(GROUPING_KEY, groupingKey, NAME, LEAF));
this.template.createRelationshipBetween(root, leaf, Relationships.LEAF.name(),
map());
}
}
对于此测试,我使用gcr
缓存来避免垃圾收集器问题:
cache_type=gcr
node_cache_array_fraction=7
relationship_cache_array_fraction=5
node_cache_size=400M
relationship_cache_size=200M
此外,我将MAVEN_OPTS
设置为:
export MAVEN_OPTS="-Xmx4096m -Xms2046m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit"
但无论如何,当运行该测试时,我总是会收到Java heap space
错误:
java.lang.OutOfMemoryError: Java heap space
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
at java.lang.Class.getMethod0(Class.java:2670)
at java.lang.Class.getMethod(Class.java:1603)
at org.apache.commons.logging.LogFactory.directGetContextClassLoader(LogFactory.java:896)
at org.apache.commons.logging.LogFactory$1.run(LogFactory.java:862)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.commons.logging.LogFactory.getContextClassLoaderInternal(LogFactory.java:859)
at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:423)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:685)
at org.springframework.transaction.support.TransactionTemplate.<init>(TransactionTemplate.java:67)
at org.springframework.data.neo4j.support.Neo4jTemplate.exec(Neo4jTemplate.java:403)
at org.springframework.data.neo4j.support.Neo4jTemplate.createRelationshipBetween(Neo4jTemplate.java:367)
我做了一些测试,数据量较少,导致以下结果。 1个节点连接到:
以下是这些操作期间系统监视器的屏幕截图:
为了更好地了解正在运行的内容并将其存储在堆中,我使用最后一个测试运行了JProfiler(800000个叶子)。以下是一些截图:
堆使用情况:
CPU使用率:
对我来说最大的问题是:neo4j是不是设计用于使用那种大量的数据?还是有其他方法来实现这种插入(以及后来的操作)?在官方的neo4j网站和各种截屏视频中,我发现了neo4j能够运行数十亿个节点和关系的信息(例如http://docs.neo4j.org/chunked/stable/capabilities-capacity.html)。我没有找到任何可用的flush()
和clean()
方法等功能,例如在JPA中手动保持堆清洁。
能够将neo4j与这些数据量一起使用会很棒。已经有200000个叶子存储在图表中,我注意到与嵌入式经典RDBMS相比,因子10的性能改进和更多。我不想放弃数据建模的好方法,也不想像neo4j那样查询这些数据。
答案 0 :(得分:3)
通过使用Neo4j核心API,创建孩子需要18到26秒,而我的MacBook Air没有任何优化:
输出:导入100万名儿童需要26秒。
public class CreateManyRelationships {
public static final int COUNT = 1000 * 1000;
public static final DynamicRelationshipType CHILD = DynamicRelationshipType.withName("CHILD");
public static final File DIRECTORY = new File("target/test.db");
public static void main(String[] args) throws IOException {
FileUtils.deleteRecursively(DIRECTORY);
GraphDatabaseService gdb = new GraphDatabaseFactory().newEmbeddedDatabase(DIRECTORY.getAbsolutePath());
long time=System.currentTimeMillis();
Transaction tx = gdb.beginTx();
Node root = gdb.createNode();
for (int i=1;i<= COUNT;i++) {
Node child = gdb.createNode();
root.createRelationshipTo(child, CHILD);
if (i % 50000 == 0) {
tx.success();tx.finish();
tx = gdb.beginTx();
}
}
tx.success();tx.finish();
time = System.currentTimeMillis()-time;
System.out.println("import of "+COUNT+" children took " + time/1000 + " seconds.");
gdb.shutdown();
}
}
和Spring Data Neo4j docs state,它不适用于此类任务
答案 1 :(得分:1)
如果要将800K子节点连接到一个节点,则实际上是在创建一个密集节点,即.k.a.键值结构。 Neo4j现在没有被优化来有效地处理这些结构,因为所有连接的关系在遍历节点时被加载到存储器中。如果您只想在触摸这些结构时加载部分关系,Neo4j 2.1将通过可配置的优化来解决这个问题。
目前,我建议将这些结构放入索引中,然后对连接的节点进行查找,或者沿着一个值平衡密集结构(例如,沿着其中一个属性构建一个子树,例如100个子类别)关系,例如时间,例如见http://docs.neo4j.org/chunked/snapshot/cypher-cookbook-path-tree.html。
那会有帮助吗?