如何使用Pattern Comprehension降低数据库访问量,优于collect语句
问题
我尝试用Pattern Comprehension优化Cypher查询,结果反而越改越困惑。
初始查询:
MATCH (a:Actor)-[:ACTED_IN]->(m:Movie) WHERE 2000 <= m.year <= 2005 AND a.born.year >= 1980 RETURN a.name AS Actor, a.born AS Born, collect(DISTINCT m.title) AS Movies ORDER BY Actor
执行Profiling后的结果:
Cypher version: , planner: COST, runtime: PIPELINED. 41944 total db hits in 152 ms.
第一次改写后的查询:
profile MATCH (a:Actor) WHERE a.born.year >= 1980 // Add a WITH clause to create the list using pattern comprehension with a match (a)-[:ACTED_IN]-(m:Movie) where 2000 <= m.year <= 2005 // filter the result of the pattern comprehension to return only lists with elements // return the Actor, Born, and Movies return a.name as Actor, a.born as Born, [(a)-[:ACTED_IN]-(m) | m.title] as Movies order by a
Profiling结果:
Cypher version: , planner: COST, runtime: PIPELINED. 47879 total db hits in 47 ms.
第二次改写后的查询:
profile MATCH (a:Actor) WHERE a.born.year >= 1980 // Add a WITH clause to create the list using pattern comprehension // filter the result of the pattern comprehension to return only lists with elements // return the Actor, Born, and Movies with a, [ (a)-[:ACTED_IN]-(m:Movie) where 2000 <= m.year <= 2005 | m.title] as Movies return a.name as Actor, a.born as Born, Movies order by a
Profiling结果:
Cypher version: , planner: COST, runtime: PIPELINED. 59251 total db hits in 6 ms.
每次改写后数据库访问量(DB hits)都比初始查询更高。我可以查看查询计划了解差异,但想知道:有没有办法用Pattern Comprehension实现比初始collect语句更少的数据库访问量?
回答
当然可以,你之前的改写存在两个核心问题,导致DB hits升高:
- 第一次改写中,先通过MATCH遍历了
a和关联的m,之后又在Pattern Comprehension里重复遍历(a)-[:ACTED_IN]-(m),等于做了两次关系遍历,额外增加了DB hits。 - 第二次改写没有处理重复项——初始查询用了
collect(DISTINCT)去重,但你的Pattern Comprehension直接返回所有匹配结果,若存在演员与同一部电影的重复关联,会导致重复遍历和取值。
优化后的Pattern Comprehension写法
MATCH (a:Actor) WHERE a.born.year >= 1980 WITH a, DISTINCT [(a)-[:ACTED_IN]->(m:Movie) WHERE 2000 <= m.year <= 2005 | m.title] AS Movies // 可选:过滤无符合条件电影的演员,与初始查询逻辑对齐 WHERE size(Movies) > 0 RETURN a.name AS Actor, a.born AS Born, Movies ORDER BY Actor
优化点说明
- 单次遍历+内置过滤:Pattern Comprehension中一次性完成关系遍历、年份过滤和标题取值,避免重复遍历关系,减少DB hits。
- 内置去重:用
DISTINCT修饰Pattern Comprehension,等价于初始查询的collect(DISTINCT),直接在生成列表时去重,比先收集再去重更高效。 - 逻辑对齐:添加
size(Movies) > 0过滤,确保只返回有符合条件电影的演员,和初始查询的结果集一致(初始查询的MATCH只会返回存在匹配电影的演员)。
额外优化建议
确保你的图数据库存在以下索引,进一步降低DB hits:
- 为
Actor节点的born.year(若born为日期类型)创建索引,加速演员出生年份的过滤。 - 为
Movie节点的year属性创建索引,快速筛选2000-2005年的电影。
内容的提问来源于stack exchange,提问作者drdot
相关产品推荐
相关产品推荐

