问题描述
为什么当我在下面提出请求时:
PROFILE MATCH (c1:Concept)-[:AT]->(ctx:Context{uid:'60156a60-d3e1-11ea-9477-f71401ca7fdb'})
WITH disTINCT c1 RETURN c1;
PROFILE MATCH (c1:Concept)-[:AT]->(ctx:Context{uid:'60156a60-d3e1-11ea-9477-f71401ca7fdb'})
WITH disTINCT c1
MATCH (c2:Concept)-[:AT]->(ctx:Context{uid:'60156a60-d3e1-11ea-9477-f71401ca7fdb'})
RETURN c1;
哪个是一样的,它会拖延我的 Neo4J 数据库?
我使用 3.3.9。
解决方法
导出的 PROFILE 计划图像应该会显示问题,但我可以猜到。
重要的是要记住,使用 Cypher,操作是按行执行的。一开始,您只有一行。
所以这里查询的第一部分:
MATCH (c1:Concept)-[:AT]->(ctx:Context{uid:'60156a60-d3e1-11ea-9477-f71401ca7fdb'})
WITH DISTINCT c1
这会执行一次,现在每个不同的 c1
节点都有一行。例如,假设此时查询中有 1000 行结果。现在是查询的其余部分:
...
MATCH (c2:Concept)-[:AT]->(ctx:Context{uid:'60156a60-d3e1-11ea-9477-f71401ca7fdb'})
RETURN c1;
此处的 MATCH(可能包括索引查找或标签扫描+过滤器,然后是扩展,然后是标签过滤)按每个输入行执行。因此,如果您在中途有 1000 行,那么现在您正在为这些行中的每一行执行整个 MATCH 序列,这样会发生 1000 次。您的行正在成倍增加需要完成的操作工作,执行时间也会成倍增加。
您应该在 PROFILE 计划中流动的行数中看到证明。观察 c1 的行如何进入下一个 NodeIndex Seek(或 NodeByLabelScan 和 Filter)操作,以及它如何持续到查询结束。