我通过UNWIND
查询(neo4j 3.4.7、30 GB堆,30 GB页面缓存)添加关系:
UNWIND { rels } AS rel
MATCH (a:Locus), (b:Snp)
WHERE a.chr = rel.start_chr AND a.start = rel.start_start AND a.end = rel.start_end AND a.ref = rel.start_ref AND b.sid = rel.end_sid
CREATE (a)-[r:TEST_MAPS]->(b)
SET r = rel.properties
以下是示例参数:
:param rels => [{start_chr: '6', start_start: 93922926, start_end: 93922926, start_ref: 'h37', end_sid: 'rs782706', properties: {source: 'binder_immuno', uuid: 'e2ee1287-9894-4eb4-8ba8-d8adc4959e50'}}]
使用:Snp(sid)
和:Locus(chr, start, end, ref)
为属性建立索引。
问题:添加关系非常缓慢。
创建关系时,查询计划者在NodeIndexSeek
上使用快速a:Locus
,但在NodeIndexScan
上使用慢得多的b:Snp
(至少慢一个数量级) )。
计划者的选择似乎取决于所使用的标签,即与其他标签以相同的方式添加关系很快并且仅使用NodeIndexSeek
。
我知道我可以强迫计划者对b:Snp
使用搜索。但是,是否有一种方法可以告诉Cypher在索引可用时始终执行查找而不更改查询?
答案 0 :(得分:1)
Cypher不保证将如何检索信息。执行的计划会根据您正在运行的Neo4j(计划程序)版本以及计划时的内部数据库统计信息而有所不同。
这就是Cypher完全拥有hints的原因。有时内部统计信息会欺骗计划者来决定一个次优的计划。
可能能够获得所需结果的一种方法是在可能的地方内联属性匹配。就像做MATCH (a:Locus), (b:Snp{sid:rel.end_sid})
。这不能保证会更改最终计划,但是通常将尽可能多的WHERE移入MATCH部分似乎可以得到更好的计划。 (对于更复杂的查询。对于简单的查询,没有什么区别。里程会根据您所运行的Neo4j版本而有所不同。)