Gremlin 相关查询会降低性能

Gremlin correlated queries kill performance

我知道这个问题的实现细节因素,但我也意识到我在这里可能做错了什么。如果是这样,我可以做些什么更好?如果 Gremlin 有一些我不知道的多结果集提交查询批处理功能,那将解决问题。比如,嘿 Gremlin,运行 这三个并行查询并给我它们的结果。

本质上,我需要知道一个顶点何时有某条边,如果没有那条边,我需要拉一个空白。所以...

g.V().as("v").coalesce(outE("someLabel").has("someProperty","someValue"),constant()).as("e").select("v","e")

该查询比使用以下方法简单地获取边10x 更昂贵:

g.V().outE("someLabel").has("someProperty","someValue")

因此,如果我想获得一组带有边或空白占位符的顶点,我有两个选择:进行两个离散查询和 "join" API 中的数据,或者进行一个非常昂贵的查询。

我的工作假设是在 Gremlin 中,我们“一次性完成”,而这实际上可能是完全错误的。也就是说,我也知道拉回数据块并有效地在 API 中进行连接是不好的做法,因为它破坏了封装原则。它还增加了往返开销。

好的,所以我找到了一个荒谬但快速的解决方案。它涉及伪造遍历,所以如果有更好的方法,让我先道歉...

g.inject(true).
union(
  __.V().not(outE("someLabel")).constant().as("ridiculous"),
  __.V().outE("someLabel").as("ridiculous")
).
select("ridiculous")

本质上,我必须写两次查询。一次遍历我想要的边,再一次遍历缺少边的地方。因此,如果我有 n 个存在/不存在的检查,我将需要 2 ^ n 个查询副本,每个副本都有自己的检查组合,以便获得最佳性能。不幸的是,采用这种方法存在堆栈溢出的风险,更不用说使代码无法可靠地管理了。

您的原始查询返回顶点-边对,而您的答案 returns 仅返回边。

您只需 运行 g.E().hasLabel("somelabel") 即可获得相同的结果。

可能比您的原始查询更快的替代方法是:

g.E().hasLabel("somelabel").as("e").outV().as("v").select("v","e")

或者

g.V().as("v").outE("somelabel").as("e").select("v","e")

If Gremlin has some multi-resultset submit queries batch feature I don't know about, that would solve the problem

Gremlin/TinkerPop 没有内置此类功能。至少有一个图表确实具有某种形式的 Gremlin 批处理 - DataStax Graph...不确定其他图表。

我也不确定我是否真的有任何您可能会觉得有用的答案,但是虽然我不希望这两个遍历之间的性能有 10 倍的差异,但我希望第一个在大多数图表上表现更差数据库。基本上,使用带有 as() 的命名步骤可以实现对遍历的路径计算要求,从而增加成本。在优化 Gremlin 时,我最早采取的步骤之一是尝试寻找方法来排除任何可能造成这种情况的因素。

这个问题似乎与您在 Jagged Result Array 上提出的另一个问题有关,但我无法维持从一个问题到另一个问题的上下文以了解如何进一步阐述。