为什么适度的 MATCH 和 CREATE 查询会在 Neo4j 浏览器中旋转?

Why does a modest MATCH and CREATE query spin in Neo4j browser?

概述

我正在使用 Neo4j 桌面浏览器创建网站内页面关系图。我确信 csv load 可以提高效率,但这个查询似乎不会引起那么多问题。

  1. 创建节点的时间比预期的要长(语法偏好?)
  2. 关系创建旋转和时间 out/crashes

。 . .

问题 1

创建节点的时间比预期的要长(语法偏好?)

我正在创建大约 6,500 个非常基本的节点(每个节点包含 1 条信息):

create (a1:link {description:"www.samplelink.com/example1"})

我正在 Excel 中构建查询并将其复制粘贴到 neo4j 浏览器中。我可以通过以下两种方式之一构建它:

create (a1:link {description:"www.samplelink.com/example1"})
create (a2:link {description:"www.samplelink.com/example2"})
create (a3:link {description:"www.samplelink.com/example3"})
...x6,000

create (a1:link {description:"www.samplelink.com/example1"}),
(a2:link {description:"www.samplelink.com/example2"}),
(a3:link {description:"www.samplelink.com/example3"}),
...x6,000

问:是否有首选语法?各自有什么优势? 6,500 个节点(尤其是没有大量信息的基本节点),似乎不会有巨大的性能提升。查询需要 5 分钟到 15 分钟以上,程序规定的实际运行时间为 7,000 毫秒或 47,000 毫秒。但是实际的浏览器旋转比规定的最终运行时间要长得多。

。 . .

问题 2

关系创建旋转和时间 out/crashes

我构建(我的解释是)非常简单的匹配子句来分配昵称。字符串匹配是文字(没有正则表达式),没有图形遍历,关系很简单。

match (a1:link {description:"www.samplelink.com/example1"})
match (a2:link {description:"www.samplelink.com/example2"})
match (a3:link {description:"www.samplelink.com/example3"})
...x6,000

create (a1)-[:REF]->(a3)
create (a1)-[:REF]->(a47)
create (a5832)-[:REF]->(a9)
...x5,000

此查询运行了 2 个多小时,然后 crashes/times 结束。

问:再一次在语法方面,我是不是在做一些非常耗费内存的事情?这应该以稍微不同的方式写吗?一个带逗号的 MATCH 短语?为关系创建一个短语?

。 . .

我的阅读材料

1.我考虑了这篇关于基数的文章:

https://neo4j.com/developer/kb/understanding-cypher-cardinality/

似乎我可能不小心创建了一个巨大的关系交叉产品,而不是按预期创建每个单一关系...?我也不知道 MATCH 语法是否对 neo4j 输出“行”的方式做了一些有趣的事情,将它们保存在内存中,然后对每一行执行所需的操作。

在一个 MATCH 短语中进行 MATCH 效率更高吗?与关系的 CREATE 相同。

MATCH (a1:link {desc:"alpha"}),
(a2:link {desc:"beta"}),
(a3:link {desc:"gamma"})

2。索引

我看到很多地方有人在评论其他旋转查询帖子,以创建索引。

我确实尝试创建一个索引 CREATE INDEX ON :link(description),但是来自 SQL 的背景,我不明白这将如何显着加快只有 6,500 个文字字符串匹配的查询。

3。类似挂起问题

Neo4j crashes on batch import

批准的答案,第三点,建议将其分解为每个 MATCH/CREATE 100 个较小的交易。我想我可以做到这一点?为了确保我的 MATCH 子句包含 CREATE 部分的正确节点,Excel 中似乎有很多摆弄。似乎 neo4j 应该能够处理内存中的 6,500 个节点和 5,000 个基本关系...我在这里没有做任何高级操作。

更新

我现在重新运行查询,格式是“MATCH节点,节点,节点”,不是“MATCH节点MATCH节点MATCH节点”格式。我只有 1 个 CREATE 语句,2 个节点之间的随机关系。这个(显然是巨大的)MATCH 子句和一个 CREATE 子句需要 15 分钟以上。所以我认为这是将所有节点保存在内存中的问题。

查询以错误结束:“Neo.TransientError.General.WhosebugError - 堆栈大小不足以执行当前任务。这通常被认为是数据库错误,因此请联系 Neo4j 支持。您可以尝试增加堆栈大小:例如,要将堆栈大小设置为 2M,请在 neo4j 配置中添加 `dbms.jvm.additional=-Xss2M'(通常在 'conf/neo4j.conf' 中,或者,如果您使用的是 Neo4j Desktop,可以通过用户界面)或者如果您是 运行 嵌入式安装,只需添加 -Xss2M 作为命令行标志。

我构建的非常基础 MATCH node1 MATCH node2 CREATE (node1)-[:REL]->(node2);并将这些查询串在一起。每个迷你查询连续运行,但在我的 Neo4j 浏览器中,每个查询实际上需要 2 秒(在 process/compile 初始查询预热 30 秒之后)。按照这个速度,300 个查询需要 10 分钟。我有 5,000 份陈述要通过。当人们使用 thousands/millions/billions 个节点创建图形时,必须有一种更有效的方法。是不是像“不要使用 Neo4j 浏览器”那么简单?并使用 csv 加载?

而不是像这样将数据预处理为密码格式:

match (a1:link {description:"www.samplelink.com/example1"})
match (a2:link {description:"www.samplelink.com/example2"})
match (a3:link {description:"www.samplelink.com/example3"})
...x6,000

create (a1)-[:REF]->(a3)
create (a1)-[:REF]->(a47)
create (a5832)-[:REF]->(a9)
...x5,000

您想将数据预处理成 CSV 文件,例如:

link_from, link_to
samplelink1,samplelink2

然后使用LOAD CSV语句导入数据:

LOAD CSV WITH HEADER FROM "file:///yourfile.csv" as row
MERGE (from:link{description:row.link_from})
MERGE (to:link{description:row.link_to})
MERGE (from)-[:REF]->(to)

通过适当的索引设置,导入应该只需要一秒钟。

问题 1:您应该将 parameter 中所有 description 值的列表传递给查询。并且查询可以只使用 UNWIND 从该列表中获取元素。查询将非常小并且执行速度更快(并且还可以避免 Cypher 注入攻击)。

例如(如果列表在descriptions参数中传递):

UNWIND $descriptions AS desc
CREATE (a1:link {description: desc})

您可能希望将非常大的列表分成较小的块,但 6500 并不是很大。

问题 2:您可以使用@TomažBratanič 的方法,或者您可以使用类似于我对问题 1 的方法的方法。也就是说,您可以传递 description 值到您的查询。

例如,如果 descriptionPairs 参数的每个元素都是 2 个 description 值的列表:

UNWIND $descriptionPairs AS descPair
MATCH (a1:link {description: descPair[0]})
MATCH (a2:link {description: descPair[1]})
CREATE (a1)-[:REF]->(a2)

而且,要使此查询非常快,您还应该在 :link(description) 上创建一个 index

注意:如果您想避免创建重复的节点或关系,您应该使用 MERGE instead of CREATE for both of my approaches. You should carefully read the documentation for MERGE 以便您了解如何正确使用它,但上述查询非常简单,只需替换 CREATE MERGE 是安全的。