【问题标题】:Gremlin correlated queries kill performanceGremlin 相关查询会扼杀性能
【发布时间】:2019-10-25 19:47:01
【问题描述】:

我了解实现细节会影响这个问题,但我也意识到我在这里可能做错了什么。如果是这样,我还能做些什么更好?如果 Gremlin 有一些我不知道的多结果集提交查询批处理功能,那将解决问题。就像,嘿 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 中有效地进行连接是不好的做法,因为它破坏了封装原则。它还增加了往返开销。

【问题讨论】:

    标签: gremlin


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      您可以运行 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")
      

      【讨论】:

      • “基本上,我需要知道一个顶点何时有某个边,如果它没有那个边,我需要拉一个空白。”如果我不需要顶点,那么删除顶点部分会很棒。该 sn-p 是一个更大、非常复杂的查询的一部分。
      • 所以把它倒过来。我会将其添加到我的答案中。
      • 首先,它会像您在原始问题中所要求的那样返回顶点-边对,同时过滤没有边的顶点,就像您通过返回空常量()所做的那样。如果你关心其他顶点,有很多方法可以做到,但我不会再花时间回答你了。祝你好运!
      【解决方案3】:

      如果 Gremlin 有一些我不知道的多结果集提交查询批处理功能,那将解决问题

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

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

      这个问题似乎与您在Jagged Result Array 上的另一个问题有关,但我在维护从一个问题到另一个问题的上下文以了解如何进一步阐述时遇到了麻烦。

      【讨论】:

      • 感谢回答,问题有关系;一个性能优化练习的所有部分。我正在将事情分解成部分并寻找性能杀手,这就是其中之一。我挖掘得越多,我就越发现让 Gremlin 通过一条路线然后进行后续查询以获取更多数据会更快。
      • 可能是这样。有时两个单独的查询可能会胜过一个。虽然我没想到会出现这种情况,但正如我在其他地方所说的那样,我不太了解 CosmosDB。如果您进行两次遍历,您可能会考虑将顶点列表传递给g.V(verticesFromFirstQuery),而不是再次执行g.V().hasLabel()。大多数图表在前者下的表现要好于后者。
      • 完全同意您从第一个查询中发送顶点 ID。我在另一个关于可扩展性的问题中找到了该解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-03
      • 2023-03-05
      • 2015-04-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多