目前,我正在开展一个在网络分析领域实施Neo4j(V2.2.0)数据库的项目。加载一些样本后,我尝试加载大数据集(> 1GB,> 4M行)。我面临的问题是,随着数据大小的增长,MERGE命令的使用会花费更多的时间。当不是每一行都必须作为一个节点加载时,在线资源对于加载大数据集的最佳方式是模棱两可的,我想对这个主题有一些清晰度。要强调的是,在这种情况下我只是加载节点;关系是下一步。
基本上有三种方法
i)为属性设置唯一性约束,并创建所有节点。该方法主要在引入MERGE命令之前使用。
CREATE CONSTRAINT ON (book:Book) ASSERT book.isbn IS UNIQUE
接着是
USING PERIODIC COMMIT 250
LOAD CSV WITH HEADERS FROM "file:C:\\path\\file.tsv" AS row FIELDTERMINATOR'\t'
CREATE (:Book{isbn=row.isbn, title=row.title, etc})
根据我的经验,如果找到重复项,则会返回错误,从而停止查询。
ii)合并节点及其所有属性。
USING PERIODIC COMMIT 250
LOAD CSV WITH HEADERS FROM "file:C:\\path\\file.tsv" AS row FIELDTERMINATOR'\t'
MERGE (:Book{isbn=row.isbn, title=row.title, etc})
我试过以这种方式装载我的装置,但是让这个过程运行超过36个小时并停止运转后,我认为应该有一个更好的替代方案,因为我的最终〜750K节点的~200K被加载
iii)基于一个属性合并节点,然后设置其余属性。
USING PERIODIC COMMIT 250
LOAD CSV WITH HEADERS FROM "file:C:\\path\\file.tsv" AS row FIELDTERMINATOR'\t'
MERGE (b:Book{isbn=row.isbn})
ON CREATE SET b.title = row.title
ON CREATE SET b.author = row.author
etc
我现在正在运行测试(~20K节点),看看从方法ii到iii的切换是否会改善执行时间,因为较小的样本会产生相互矛盾的结果。有没有我监督的方法,可以缩短执行时间?如果我没有弄错,批处理插件只适用于CREATE命令,而不适用于MERGE命令。
我允许Neo4j使用4GB内存,从我的任务管理器判断这已足够(仅使用3GB以上)。
答案 0 :(得分:1)
方法iii)应该是您MERGE
针对单个属性的最快解决方案。在执行MERGE
之前是否创建了唯一性约束?如果没有索引(约束或普通索引),则该过程将花费很长时间来处理越来越多的节点。
CREATE CONSTRAINT ON (book:Book) ASSERT book.isbn IS UNIQUE
其次是:
USING PERIODIC COMMIT 20000
LOAD CSV WITH HEADERS FROM "file:C:\\path\\file.tsv" AS row FIELDTERMINATOR'\t'
MERGE (b:Book{isbn=row.isbn})
ON CREATE SET b.title = row.title
ON CREATE SET b.author = row.author
这应该有用,你可以增加PERIODIC COMMIT
。
我可以在几分钟内添加几十万个节点。
答案 1 :(得分:0)
通常,请确保您已准备好索引。首先根据索引的属性合并节点(以利用快速查找),然后根据需要使用SET
修改该节点的属性。
除此之外,您的两种方法都是通过事务层进行的。如果你需要很快地将大量数据插入到数据库中,你可能不希望使用事务来执行此操作,因为它们会为您提供您可能不需要的功能,并且它们需要开销会降低您的速度。因此,更大的解决方案是不使用LOAD CSV
插入数据,而是完全转到另一条路径。
如果你正在使用2.2系列的neo4j,你可以使用batch inserter via java,或者{2.2}之前可用的neo4j-import tool。它们的共同之处在于它们不使用交易。
最后,无论你走到哪里,你应该阅读Michael Hunger's article on importing data into neo4j,因为它提供了一个很好的概念性讨论,如果你要将大量数据加载到neo4j中,你需要跳过事务。