所以我尝试将一些邮政编码和地址数据加载到neo4j中。我认为有一个独特的约束有三个标签。 POSTCODE,ADDRESS和REGION。 REGION和POSTCODE对其单一属性有独特的限制。我们用于插入的查询将是MERGE REGION,MERGE POSTCODE CREATE ADDRESS,然后是CREATE RELATIONSHIPS。我们的想法是能够看到哪些邮政编码在哪个区域,以及共享一个邮政编码的地址数量,因此MERGE行为非常重要。
然而,我们发现一旦数据库达到相当适中的大小,这将非常缓慢。现在我们预料到了这一点,但我们预计约束检查应该按log(n)进行扩展。相反,性能在数据库大小上是线性的,这是非常意外的。
如果不放弃MERGE行为,我该怎么做才能改善这一点?这是UNIQUE约束的结果吗?理论上,在使用merge时只有一个唯一约束和只有一个索引之间应该没有区别,因为只有一个属性。合并需要知道属性是否存在以决定是否合并。
我知道我可以做各种事情来加速插入,使用csv加载器等。我对这里提高渐近性能很感兴趣。我认为唯一约束应该有O(log(n))的时间成本,而不是O(n),这可能会产生巨大的差异。
编辑:进一步调查显示,问题不是索引查找,而是将R树插入空间层。用于插入的特定代码使用嵌入式API,而不是cypher和代码段:graphDB.index().forNodes(s).add(node, "dummy", "variable");
随着树的大小扩展,在O(n)处逐渐变慢。这显然是R-Trees的预期行为。这需要大约0.0005 *层中的节点数。删除空间插入后,它会快几个数量级,并且不会显示缩放行为。我认为减少的原因是缓存在启动后升温。
我在使用以下代码启动空间索引:
Map<String, String> config = SpatialIndexProvider.SIMPLE_POINT_CONFIG;
Transaction tx = graphDB.beginTx();
IndexManager indexMan = graphDB.index();
try{
indexMan.forNodes(lab.name(), config);
tx.success();
} finally {
tx.close();
}
这样可以为您提供Cypher入口点,但索引和层之间是否存在质量差异?一个层是否具有比索引更好的性能,或者它们都由相同的R树支持。
这个问题的建议:Neo4J huge performance degradation after records added to spatial layer似乎是我应该在启动空间层之前将所有节点放入数据库,因为它的索引要比增量插入快得多。
我明天试试。
答案 0 :(得分:1)
你使用哪种Neo4j版本?
是的,请分享您的疑问。
如果您使用LOAD CSV
,则首先使用MERGE
分别创建节点,然后在第二遍中创建与MATCH ... MATCH ... CREATE ...
另见:http://www.markhneedham.com/blog/2014/10/23/neo4j-cypher-avoiding-the-eager/
如果您不使用LOAD CSV,您是否运行个别小型交易? 如果是这样,将它们批量处理为每个事务1000例操作是有意义的。
您是否也可以使用浏览器中的“:schema”或shell中的“schema”验证您的约束是否到位?
通过在shell中分析查询来检查索引/约束是否实际使用?
只需在其前面添加profile
。