查询两顶点间路径长度时,size()为何比length()更快?
为什么在图查询中
size(e)比length(p)快近一倍? 问题背景
我构建了一个映射维基百科文章的图结构:
- 顶点代表维基百科文章
- 边表示当前文章正文首个链接指向的目标文章
- 所有文章最终都关联到「Philosophy(哲学)」节点
- 整个图包含27个顶点和26条边
在查询两个顶点间的路径长度时,我发现使用size(e)的查询速度几乎是length(p)的两倍,测试代码及结果如下:
demo=# \timing on Timing is on. demo=# SELECT * FROM cypher('Wikipedia', $$ MATCH p = (a)-[e:RELATED_TO*]->(b) WHERE a.name = 'Tulpa' AND b.name = 'Philosophy' RETURN size(e) $$) AS (edge_count agtype); edge_count ------------ 18 (1 row) Time: 4.724 ms demo=# SELECT * FROM cypher('Wikipedia', $$ MATCH p = (a)-[e:RELATED_TO*]->(b) WHERE a.name = 'Tulpa' AND b.name = 'Philosophy' RETURN length(p) $$) AS (edge_count agtype); edge_count ------------ 18 (1 row) Time: 7.280 ms
原因分析
核心差异来自两个函数的底层实现逻辑和查询引擎的处理方式:
size(e)的高效性:
这里的e是匹配路径时直接捕获的边集合([e:RELATED_TO*])。查询引擎在遍历路径的过程中,已经实时维护了这条路径的边列表,size(e)只是直接读取该集合已统计好的元素数量,几乎没有额外计算开销。length(p)的额外开销:p是完整的路径对象,length(p)虽然最终返回的也是路径中边的数量,但引擎处理该函数时,需要对路径对象进行遍历或从路径的元数据中重新解析计算边的数量——这个过程相比直接读取边集合的size,多了一层数据访问或遍历操作,因此带来了明显的耗时差异。
即使在小图场景(27个节点)下,这种底层实现的差异也能直接体现在查询耗时上。
内容的提问来源于stack exchange,提问作者Matheus Farias
相关产品推荐
相关产品推荐

