我正在运行一个Cypher查询,让所有朋友远离某个来源最多3跳:
MATCH (:Person {id:"768"})-[:KNOWS*1..3]-(friend:Person)
WITH DISTINCT friend
RETURN count(friend)
查询会返回正确的结果,但由于图表中只有10k人,因此需要更长的时间。当我对查询进行概要分析时,我发现VarLengthExpand(All)
运算符返回了大量的行(~282k):
+-----------------------+----------------+--------+---------+
| Operator | Estimated Rows | Rows | DB Hits |
+-----------------------+----------------+--------+---------+
| +ProduceResults | 6 | 1 | 0 |
| | +----------------+--------+---------+
| +EagerAggregation | 6 | 1 | 0 |
| | +----------------+--------+---------+
| +Distinct | 35 | 9082 | 0 |
| | +----------------+--------+---------+
| +Filter | 37 | 282635 | 282635 |
| | +----------------+--------+---------+
| +VarLengthExpand(All) | 37 | 282635 | 290014 |
| | +----------------+--------+---------+
| +NodeIndexSeek | 1 | 1 | 2 |
+-----------------------+----------------+--------+---------+
似乎VarLengthExpand(All)
步骤正在做更多的工作。为了检查这一点,我查看了每个最小距离的节点数,以及与这些节点的事件KNOWS
关系的数量:
----------------------------------------------------
| min. dist. from src: | 0 | 1 | 2 | 3 |
|----------------------|----|------|--------|------|
| nodes | 1 | 12 | 2815 | 6270 |
| incident knows rels | 12 | 3697 | 164828 | |
----------------------------------------------------
因此,我们看到节点768有12个直接朋友,2,815个朋友朋友和6,270个朋友朋友。朋友朋友组有164,828个事件KNOWS
关系,在这些关系触及的所有节点中,6,270个节点与源节点的最小距离为3。
所以,如果一个遍历是从源头以广度优先搜索的方式进行的......理论上它只需要做~12 + 3,697 + 164,828 = 168,537次读取,这远远低于282k
有人知道这里发生了什么,以及是否有更好的方法来制定此查询?