Neo4j不使用索引

3

目前我正在尝试在Neo4j 2.2.2上运行此查询。

在发布此文章时,我们还没有将任何节点标记为我们最近从Neo4j 1.x升级。因此,我们无法使用USING子句选项。

我尝试使用索引,但最终只得到了全表扫描。

START pfComp=node:Company('id:2403226') , ptComp=node:Company('id:1946633')
OPTIONAL MATCH
     (pfComp)<-[c:CHILD_OF*]-(cfComp)
WITH collect(id(cfComp)) as cfCompIds, ptComp, pfComp
OPTIONAL MATCH
                (ptComp)<-[c2:CHILD_OF*]-(ctComp)
WITH  cfCompIds, collect(id(ctComp)) AS ctCompIds
MATCH
                (fComp) -[fR:PARTICIPATES_IN]->  cdeals <-[tR:PARTICIPATES_IN]-(tComp)
WHERE
                (fComp.id = 2403226 or id(fComp) in  cfCompIds) and
                (tComp.id = 1946633 or id(tComp) in ctCompIds)
RETURN fComp, tComp, cdeals

密码版本: CYPHER 2.2,计划器: COST。在79128毫秒内,共计1305292个数据库命中。

非常感谢您的任何帮助。

以下是完整的profile命令输出。

这是查询的解释计划

查询的开始部分执行得很快:

profile START pfComp=node:Company('id:2403226') , ptComp=node:Company('id:1946633')
OPTIONAL MATCH
     (pfComp)<-[c:CHILD_OF*]-(cfComp)
WITH collect(id(cfComp)) as cfCompIds, ptComp, pfComp
OPTIONAL MATCH
                (ptComp)<-[c2:CHILD_OF*]-(ctComp)
return   cfCompIds, collect(id(ctComp)) AS ctCompIds

密码版本:CYPHER 2.2,计划程序:COST。582毫秒内总共有836个数据库命中。

在此输入图片描述


也许您在这里输错了?您使用了未初始化的标识符,因此必须进行非常不好的全扫描和展开: OPTIONAL MATCH (ptComp)<-[c2:CHILD_OF*]-(ctComp) - Michael Hunger
这里的定义查找方式不一致,对于属性查找,您缺少标签和id()查找与prop查找冲突。我会将其拆分为联合的两个部分。 - Michael Hunger
Michael Hunger: 查询的开头部分没问题:profile START pfComp=node:Company('id:2403226') , ptComp=node:Company('id:1946633') OPTIONAL MATCH (pfComp)<-[c:CHILD_OF*]-(cfComp) WITH collect(id(cfComp)) as cfCompIds, ptComp, pfComp OPTIONAL MATCH (ptComp)<-[c2:CHILD_OF*]-(ctComp) return cfCompIds, collect(id(ctComp)) AS ctCompIds
结果: Cypher版本:CYPHER 2.2,规划器:COST。582毫秒内共有836个数据库命中。
- Ted Gulesserian
3个回答

2
你的第二部分看起来像是关系连接,或者是额外的查找(就像n+1选择)。 也许可以使用图形模型?这样查询也会更简单。
因此,你将使用初始匹配计算fComp和tComp,由于*0..包括pfComp和ptComp每个值。
然后,在最后一个匹配中,你有fComp和tComp之间的交叉点。
请尝试一下并看看它的表现如何:
MATCH (pfComp:lCompany)<-[c:CHILD_OF*0..]-(fComp:lCompany)
WHERE pfComp.id = 2403226
// reduce cardinality for following match
WITH collect(distinct fComp) as companies1
MATCH (ptComp:lCompany)<-[c2:CHILD_OF*]-(tComp:lCompany)
WHERE ptComp.id = 1946633
// create cross product between fComp and tComp
UNWIND companies1 as fComp
MATCH (fComp) -[fR:PARTICIPATES_IN]->(cdeals)<-[tR:PARTICIPATES_IN]-(tComp)
RETURN  fComp, tComp, cdeals;

没想到能有更好的表现,但你将性能提高了三倍。非常感谢您,先生。Cypher版本:CYPHER 2.2,规划器:COST。在307毫秒内总共有40525个数据库命中。 - Ted Gulesserian
好时光!使用图表Luke :) 如果您满意,请接受答案。不同之处在于使用图形操作(扩展)而不是成千上万的索引查找。 - Michael Hunger

1

您的个人资料中存在索引查询(NodeByQueryIndex)。

您可以定义要在查询中使用的索引:

MATCH (n:Swedish)
USING INDEX n:Swedish(surname)
WHERE n.surname = 'Taylor'
RETURN n

请参见http://neo4j.com/docs/stable/query-using.html


我们正在使用传统的索引。DBA刚刚添加了标签,我将使用新标记的节点重试USING子句。 - Ted Gulesserian

1
我们的解决方案是创建标签(lCompany),并在Company.id列上添加新的索引类型(CREATE INDEX ON:lCompany(id))。
然后调整查询以使用新索引:
OPTIONAL MATCH
     (pfComp:lCompany)<-[c:CHILD_OF*]-(cfComp:lCompany)
WHERE pfComp.id = 2403226
WITH 
    collect(cfComp.id) as cfCompIds
    , pfComp
OPTIONAL MATCH
        (ptComp:lCompany)<-[c2:CHILD_OF*]-(ctComp:lCompany)
WHERE ptComp.id = 1946633
WITH  cfCompIds, 
      collect(ctComp.id)  AS ctCompIds, 
      pfComp, ptComp 
MATCH
      (fComp:lCompany) -[fR:PARTICIPATES_IN]->  cdeals <-[tR:PARTICIPATES_IN]-(tComp:lCompany)
USING INDEX fComp:lCompany(id) //tComp:lCompany(id)
WHERE
                (   
                    fComp.id in (cfCompIds + [2403226])
                ) 
                and
                (
                    tComp.id in (ctCompIds + [1946633])
                )
RETURN  fComp, tComp, cdeals

可能还有其他的优化可以做,但这是我们目前为止所能做到的。

现在的分析结果如下:

Cypher版本:CYPHER 2.2,planner:COST。1498ms内总共有134151个数据库命中。

这是微调后的新配置文件:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接