优化Gremlin查询:去除Path步骤中的冗余顶点数据
Neptune中Gremlin查询的冗余开销与优化方案
问题背景
现有图结构:person顶点与book顶点通过owns边关联(person => owns => book),一个用户可拥有多本图书,示例数据如下:
{label=person, id=person_1, name=Tom, age=30} {label=person, id=person_2, name=Jerry, age=40} {label=book, id=book_1, name=Book1} {label=book, id=book_2, name=Book2} {label=book, id=book_3, name=Book3} person_1 => owns => book_1 person_1 => owns => book_2 person_2 => owns => book_3
当前使用如下Gremlin Java查询获取用户的图书拥有关系:
g.V("person_1", "person_2").outE("owns").inV().path().by(__.valueMap().with(WithOptions.tokens)).toStream().forEach(path -> { int size = path.size(); for (int counter = 0; counter < size; counter++) { Map<Object, Object> object = path.get(counter); System.out.println(counter + ": " + object); } });
查询输出中,同一用户的person顶点数据会随其拥有的每本图书重复出现。若存在10个用户各拥有100本图书,这种冗余是否会增加Neptune的数据检索或序列化开销?且dedup无法解决该问题,如何优化此查询?
问题解答
1. 冗余带来的开销影响
这种冗余肯定会增加开销:
- 数据检索与序列化层面:Neptune需要为每条路径重复提取并序列化
person顶点的valueMap数据,虽然顶点在存储中是唯一的,但序列化阶段会重复生成相同内容,额外消耗计算资源。 - 传输与客户端解析层面:10个用户各100本图书的场景下,原本仅需返回10份
person数据,现在会返回1000份重复数据,网络传输量直接放大100倍,客户端的解析、内存占用开销也会同步上升。
2. 查询优化方案
dedup无法解决是因为它针对整个路径去重,而我们需要按用户聚合图书列表。可以通过groupBy将用户与对应的图书列表关联,彻底消除用户数据的重复返回:
优化后的Gremlin查询
g.V("person_1", "person_2") .group() .by(__.valueMap().with(WithOptions.tokens)) .by(__.out("owns").valueMap().with(WithOptions.tokens).fold()) .toStream() .forEach(entry -> { Map<Object, Object> person = (Map<Object, Object>) entry.getKey(); List<Map<Object, Object>> books = (List<Map<Object, Object>>) entry.getValue(); System.out.println("用户: " + person); System.out.println("拥有图书: " + books); });
优化逻辑说明
- 使用
group()将每个person顶点作为分组的key,确保用户数据仅被序列化一次 - 通过
by(fold())将该用户所有关联的book顶点数据收集为一个列表作为value - 最终返回结构为
{用户数据: [图书列表]},完全避免了用户数据的冗余传输与解析
内容的提问来源于stack exchange,提问作者coderz
相关产品推荐
相关产品推荐

