JanusGraph/Gremlin - 重复步骤应用于大型数据集的性能问题
JanusGraph/Gremlin - Performance issue with repeat step applied to large data sets
我在查询涉及重复步骤的大型图形时遇到问题,这些步骤旨在使 "hops" 跨越顶点和边缘。我的意图是推断对象之间的间接关系。考虑以下因素:
John--livesIn-->Paris
Paris--isIn-->France
我希望得到的是 John 常驻法国。很简单,这对小数据集很有效。
我使用的查询如下,其中不超过 2 个跃点:
g.V().has('name','John')
.emit(loops().is(lt(2)))
.repeat(__.bothE().bothV().simplePath())
.inE('isIn').outV().path()
这按预期工作,直到我将其应用于由大约 1000 个顶点和 3000 条边组成的图形。然后,几分钟后,我得到了各种没有清晰逻辑的错误(通过 REST API):
- 错误:评估脚本时遇到错误
- 错误:504 网关超时
- 错误:Java堆space
- 错误
我怀疑我的查询有误。例如,将 "hops" 的数量设置为 1(直接关系)与 .emit(loops().is(lt(1)))
,我希望结果能够迅速交付,因为它不会进入重复循环。但是,这会触发相同的问题。
非常感谢您的帮助!
奥利维尔
所以看起来你在这里发生了一些事情。首先让我尝试回答您的问题,然后让我们看看为什么您的遍历可能需要很长时间才能完成。
根据你想要 return John and France 的描述,下面的遍历应该得到你的数据:
g.V().has('name','John').as('person')
out('livesIn')
.out('isIn').as('country').select('person', 'country')
这将 select 个名为 'John' 的人居住的所有国家/地区。
现在了解为什么您的遍历需要很长时间了。首先,您正在使用几个非常占用内存和资源的步骤,例如 bothE and bothV. Each of these steps navigate the relationship in both directions. Since you know the direction of the edge you are trying to traverse is out in both cases it is much quicker and less resource intensive to just use an out edge as this will traverse the specified edge name (if supplied) and end you on the adjacent vertex. Additionally, the simplePath 步骤是另一个资源(特别是内存)密集型步骤,因为它必须跟踪每个遍历器的路径值,直到它包含重复的对象,此时它被丢弃。这与使用循环和 bothE 和 bothV 创建的额外遍历器相结合很可能是查询缓慢的原因。我怀疑上面的查询会执行得更好。
如果您想确切了解您的查询在做什么,我建议您查看 explain and profile 步骤,其中提供了有关您的查询性能的详细信息。
我在查询涉及重复步骤的大型图形时遇到问题,这些步骤旨在使 "hops" 跨越顶点和边缘。我的意图是推断对象之间的间接关系。考虑以下因素:
John--livesIn-->Paris
Paris--isIn-->France
我希望得到的是 John 常驻法国。很简单,这对小数据集很有效。
我使用的查询如下,其中不超过 2 个跃点:
g.V().has('name','John')
.emit(loops().is(lt(2)))
.repeat(__.bothE().bothV().simplePath())
.inE('isIn').outV().path()
这按预期工作,直到我将其应用于由大约 1000 个顶点和 3000 条边组成的图形。然后,几分钟后,我得到了各种没有清晰逻辑的错误(通过 REST API):
- 错误:评估脚本时遇到错误
- 错误:504 网关超时
- 错误:Java堆space
- 错误
我怀疑我的查询有误。例如,将 "hops" 的数量设置为 1(直接关系)与 .emit(loops().is(lt(1)))
,我希望结果能够迅速交付,因为它不会进入重复循环。但是,这会触发相同的问题。
非常感谢您的帮助!
奥利维尔
所以看起来你在这里发生了一些事情。首先让我尝试回答您的问题,然后让我们看看为什么您的遍历可能需要很长时间才能完成。
根据你想要 return John and France 的描述,下面的遍历应该得到你的数据:
g.V().has('name','John').as('person')
out('livesIn')
.out('isIn').as('country').select('person', 'country')
这将 select 个名为 'John' 的人居住的所有国家/地区。
现在了解为什么您的遍历需要很长时间了。首先,您正在使用几个非常占用内存和资源的步骤,例如 bothE and bothV. Each of these steps navigate the relationship in both directions. Since you know the direction of the edge you are trying to traverse is out in both cases it is much quicker and less resource intensive to just use an out edge as this will traverse the specified edge name (if supplied) and end you on the adjacent vertex. Additionally, the simplePath 步骤是另一个资源(特别是内存)密集型步骤,因为它必须跟踪每个遍历器的路径值,直到它包含重复的对象,此时它被丢弃。这与使用循环和 bothE 和 bothV 创建的额外遍历器相结合很可能是查询缓慢的原因。我怀疑上面的查询会执行得更好。
如果您想确切了解您的查询在做什么,我建议您查看 explain and profile 步骤,其中提供了有关您的查询性能的详细信息。