所以我尝试将一些邮政编码和地址数据加载到neo4j中。我提出了一个独特的约束,实际上有三个标签。邮政编码、地址和地区。REGION 和 POSTCODE 对其单一属性有独特的限制。我们用于插入的查询将 MERGE REGION、MERGE POSTCODE CREATE ADDRESS,然后是 CREATE RELATIONSHIPS。这个想法是能够查看哪个地区的邮政编码,以及有多少地址共享一个邮政编码,因此 MERGE 行为很重要。
但是,我们发现一旦数据库达到相当适中的大小,这将非常缓慢。现在我们预料到了这一点,但我们希望约束检查应该缩放为 log(n)。相反,性能与数据库大小呈线性关系,这是非常出乎意料的。
在不放弃 MERGE 行为的情况下,我能做些什么来改善这一点?这是 UNIQUE 约束的结果吗?理论上,在使用合并时拥有唯一约束和仅拥有索引之间应该没有区别,因为只有一个属性。无论哪种方式,merge 都需要知道属性是否存在来决定是否合并。
我知道我可以做各种事情来加快插入速度,使用 csv 加载器等。我对提高渐近性能感兴趣。我认为独特的约束应该有 O(log(n)) 的时间成本,而不是 O(n),这可能会产生巨大的差异。
编辑:进一步调查显示问题不是索引查找,而是 R-tree 插入空间层。用于插入的特定代码使用了嵌入式 API,而不是密码和代码片段:
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-trees 支持。
对这个问题的建议:Neo4J在将记录添加到空间层后性能大幅下降似乎是我应该在启动空间层之前将所有节点放入数据库,因为它的索引速度比增量插入快得多。
明天试试。