Gremlin 小精灵相关查询会破坏性能

Gremlin 小精灵相关查询会破坏性能,gremlin,Gremlin,我理解实现细节是这个问题的一个重要因素,但我也意识到我可能在这里做错了什么。如果是这样,我还能做得更好吗?如果Gremlin有一些我不知道的multi-resultset-submit-querys批处理功能,那么问题就解决了。如中所示,嘿,Gremlin,并行运行这三个查询并给出结果 本质上,我需要知道一个顶点什么时候有一条边,如果它没有那个边,我需要拉一个空白。所以 g.V().as("v").coalesce(outE("someLabel").has("someProperty","so

我理解实现细节是这个问题的一个重要因素,但我也意识到我可能在这里做错了什么。如果是这样,我还能做得更好吗?如果Gremlin有一些我不知道的multi-resultset-submit-querys批处理功能,那么问题就解决了。如中所示,嘿,Gremlin,并行运行这三个查询并给出结果


本质上,我需要知道一个顶点什么时候有一条边,如果它没有那个边,我需要拉一个空白。所以

g.V().as("v").coalesce(outE("someLabel").has("someProperty","someValue"),constant()).as("e").select("v","e")
该查询的成本是使用以下方法获取边缘的10倍:

g.V().outE("someLabel").has("someProperty","someValue")
因此,如果我想得到一组带有边或空白占位符的顶点,我有两个选项:进行两个离散查询,并在API中“连接”数据,或者进行一个非常昂贵的查询


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

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

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

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

原始查询返回顶点-边对,其中作为答案,只返回边

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

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

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

如果Gremlin有一些我不知道的multi-resultset-submit-querys批处理功能,那么问题就解决了

小精灵/小叮当没有内置这样的功能。至少有一个图形具有某种形式的Gremlin批处理-DataStax图形…不确定其他图形

我也不确定我是否真的有任何你可能会觉得有用的答案,但尽管我不希望这两次遍历之间的性能相差10倍,但我希望第一次遍历在大多数图形数据库上的性能更差。基本上,使用带有
as()
的命名步骤可以满足遍历的路径计算要求,从而增加成本。当优化Gremlin时,我最早的步骤之一是尝试寻找方法,找出任何可能做到这一点的因素


这个问题似乎与你的另一个问题有关,但我很难将一个问题的上下文理解为另一个问题,以理解如何进一步阐述

“本质上,我需要知道顶点何时有某条边,如果它没有该边,我需要拉一个空白。”如果我不需要顶点,放下顶点部分会很棒。这段代码是一个更大、更复杂的查询的一部分,所以只需将其反转即可。我将把它添加到我的答案中。首先,它会像您在原始问题中要求的那样返回顶点-边对,同时过滤没有边的顶点,就像您通过返回空常量()所做的那样。如果你关心其他顶点,有很多方法可以做到这一点,但我不会花更多的时间回答你。祝你好运谢谢你的回答,问题是相关的;所有这些都是性能优化练习的一部分。我把事情分解成几个部分,寻找性能杀手,这就是其中之一。我挖掘得越多,我就越发现让Gremlin通过一条路径,然后进行后续查询以获取更多数据会更快。可能就是这样。有时,两个单独的查询可能比一个好。虽然我没想到会是这样,但正如我在其他地方所说的,我对CosmosDB不太了解。如果你做两个遍历,你可能会考虑把顶点列表传递给<代码> G.V(Vistice FixStQuy),而不是再次执行<代码> G.V.()。大多数图在前一种情况下会比后一种情况下表现更好。完全同意您关于从第一个查询发送顶点ID的看法。我在关于可伸缩性的另一个问题中找到了这个解决方案。
g.V().as("v").outE("somelabel").as("e").select("v","e")