【发布时间】:2014-04-07 23:10:06
【问题描述】:
我正在使用一个 neo4j 数据库,该数据库由大约 275,000 个英语单词组成,这些单词与它们所包含的字母相关联。我在 Windows 上运行 Neo4j 2.0.1 Community Edition。
我正在尝试使用以下 Cypher 将新单词节点插入图中,更新这些节点上的属性,然后在新添加单词节点时创建与现有(字母)节点的新关系:
BEGIN
MATCH (A:Letter {token:"A"}),
(B:Letter {token:"B"}),
(C:Letter {token:"C"}),
(D:Letter {token:"D"}),
(E:Letter {token:"E"}),
(F:Letter {token:"F"}),
(G:Letter {token:"G"}),
(H:Letter {token:"H"}),
(I:Letter {token:"I"}),
(J:Letter {token:"J"}),
(K:Letter {token:"K"}),
(L:Letter {token:"L"}),
(M:Letter {token:"M"}),
(N:Letter {token:"N"}),
(O:Letter {token:"O"}),
(P:Letter {token:"P"}),
(Q:Letter {token:"Q"}),
(R:Letter {token:"R"}),
(S:Letter {token:"S"}),
(T:Letter {token:"T"}),
(U:Letter {token:"U"}),
(V:Letter {token:"V"}),
(W:Letter {token:"W"}),
(X:Letter {token:"X"}),
(Y:Letter {token:"Y"}),
(Z:Letter {token:"Z"})
// Create Words and link to proper letters
MERGE (w1:Word {string:"WHOSE", length:5})
ON MATCH SET w1.s_enable1=TRUE
ON CREATE SET w1.s_enable1=TRUE
// create the letter->word relationships if necessary
CREATE UNIQUE (w1) <-[:IN_WORD {position:1}]- (W)
CREATE UNIQUE (w1) <-[:IN_WORD {position:2}]- (H)
CREATE UNIQUE (w1) <-[:IN_WORD {position:3}]- (O)
CREATE UNIQUE (w1) <-[:IN_WORD {position:4}]- (S)
CREATE UNIQUE (w1) <-[:IN_WORD {position:5}]- (E)
MERGE (w2:Word {string:"WHOSESOEVER", length:11})
ON MATCH SET w2.s_enable1=TRUE
ON CREATE SET w2.s_enable1=TRUE
CREATE UNIQUE (w2) <-[:IN_WORD {position:1}]- (W)
CREATE UNIQUE (w2) <-[:IN_WORD {position:2}]- (H)
CREATE UNIQUE (w2) <-[:IN_WORD {position:3}]- (O)
CREATE UNIQUE (w2) <-[:IN_WORD {position:4}]- (S)
CREATE UNIQUE (w2) <-[:IN_WORD {position:5}]- (E)
CREATE UNIQUE (w2) <-[:IN_WORD {position:6}]- (S)
CREATE UNIQUE (w2) <-[:IN_WORD {position:7}]- (O)
CREATE UNIQUE (w2) <-[:IN_WORD {position:8}]- (E)
CREATE UNIQUE (w2) <-[:IN_WORD {position:9}]- (V)
CREATE UNIQUE (w2) <-[:IN_WORD {position:10}]- (E)
CREATE UNIQUE (w2) <-[:IN_WORD {position:11}]- (R)
... N-2 more of these ...;
COMMIT
... M-1 more transactions ...
我正在使用 neo4j-shell 执行像这样的 Cypher 命令文件来添加新单词。大多数被合并的词已经存在于图中。只有一小部分是新的。
此代码通常可以工作,除了:(a) 它运行非常缓慢(例如,当 N = 50 时,50 秒/50 字事务),以及 (b) 当需要创建新关系时(使用 CREATE UNIQUE),事务缓慢到很多分钟,偶尔会失败并出现错误“超出 GC 开销限制”。
我还尝试使用 MERGE 代替 CREATE UNIQUE。这通常以类似的方式工作(非常慢),并在运行多个事务后最终因 Java 堆内存错误而失败。 (似乎是某种内存泄漏。)
任何关于我做错了什么和/或完成这项任务的更好方法的见解将不胜感激。
更多信息
此图主要是提供一个动手原型,以帮助理解 Neoj4 在感兴趣领域的特性和功能:语言结构、单词统计、对文字游戏有用的查询(填字游戏、拼字游戏、与朋友的单词、刽子手、. ..)。
所有属性都已编入索引(在 neo4j.properties 文件和 CREATE INDEX ON 命令中)。
s_enable1 表示要添加的单词列表的来源。在这种情况下,“enable1”字典(173,122 个单词)。初始图表是使用“sowpods”词典(267,751 个单词)创建的。 s_ 前缀代表“来源”。每次将新字典添加到图表时,都会创建一个新属性来指示哪些单词(现有的和新的)与每个列表相关联。 (例如,单词 AA 出现在 sowpods 和 enable1 字典中,因此 AA 单词节点的 s_sowpods 和 s_enable1 属性都设置为 TRUE。)
MERGE 或 CREATE UNIQUE 似乎非常适合在添加新字典时不断更新图表。
sowpods 构建创建了大约 250 万个(字母)-[:IN_WORD]->(单词)关系。 enable1 合并可能会再创建 500 K 左右。 (很多 enable1 词都很长,例如 16 - 21 个字母。)
操作系统是 Windows 7。运行 Java 7.51 x64。 (最初运行的是 x32,它慢了 2 倍。) java -XshowSettings 显示 885.5 M 最大堆。我相信数据库设置大多是默认设置。 (哪些设置特别突出?)
【问题讨论】:
-
你真正想要实现什么?您是否为匹配/合并操作创建了约束/索引? s_enable1 是什么意思?为什么你也将它设置为匹配?你的数据库中有多少关系?你的数据库设置是什么,你在什么操作系统上运行?请使用所有这些信息更新您的帖子。
-
如果你在没有任何参数的neo4j-shell中运行它,它也必须解析每个大语句。可怜的 Cypher 解析器,尝试创建只匹配他们需要的字母的更小的语句。此外,您所有的字母都将是图中的超级节点,因此您可能需要考虑查看 2.1。如果将创建关系语句放入 on create 子句中,则不需要创建唯一性。
-
感谢您的意见!不确定如何使用 neo shell 参数化我的 Cypher 脚本。 (将需要阅读。)我想知道 SET ON CREATE 构造是否允许在创建新单词节点时有条件地创建新/缺失的链接。似乎只适用于属性创建。仍然不确定如何重组事物以完成我需要的那种 MERGE 更新。欢迎提供更多提示!
-
我还将
s_enable1=true更改为 source="enable1" 和source="sowpods"应该更容易处理。 -
在 Windows 上增加堆大小(例如增加到 3 或 4G),因为 Neo4j 内存映射发生在堆内部。节点和 rel 的目标计数是多少?
标签: performance neo4j cypher