【问题标题】:How to do efficient bulk upserts (insert new vertex, or update property(ies)) in Gremlin?如何在 Gremlin 中进行高效的批量更新(插入新顶点或更新属性)?
【发布时间】:2020-06-09 05:19:51
【问题描述】:

上下文

我确实有一个包含大约 2000 个顶点和 6000 条边的图,随着时间的推移,它可能会增长到 10000 个顶点和 100000 条边。目前我正在使用以下遍历查询更新新顶点:

更新顶点和边

queryVertex = "g.V().has(label, name, foo).fold().coalesce(
               unfold(), addV(label).property(name, foo).property(model, 2)
               ).property(model, 2)"

这里的目的是查找名为 foo 的顶点,如果找到则更新其model 属性,否则创建一个新顶点并设置model 属性。这会发出两次:一次用于源顶点,然后用于目标顶点。
一旦创建了两个相关的顶点,就会发出另一个查询来创建它们之间的边:

queryEdge = "g.V('id_of_source_vertex').coalesce(
             outE(edge_label).filter(inV().hasId('id_of_target_vertex')), 
             addE(edge_label).to(V('id_of_target_vertex'))
             ).property(model, 2)"

这里,如果两个顶点之间有边,则更新边上的model属性,否则创建它们之间的边。

执行此操作的伪代码如下:

for each edge in the list of new edges:
   //upsert source and target vertices:  
   execute queryVertex for edge.source
   execute queryVertex for edge.target
   // upsert edge: 
   execute queryEdge

这行得通,但效率极低;例如,对于提到的图形大小,它需要几分钟才能完成,并且在一些应用内并发的情况下,它只减少了几分钟的时间。当然,对于如此小的图形大小,必须有一种更有效的方法。

问题
* 我怎样才能使这些 upserts 更快?

【问题讨论】:

    标签: graph gremlin tinkerpop tinkerpop3 amazon-neptune


    【解决方案1】:

    批量加载通常应委托给经过优化以处理此类任务的提供商特定工具。 Gremlin 确实没有提供抽象来涵盖实现 TinkerPop 的各种图形数据库系统的各种批量加载器工具组。对于 Neptune,这是您标记问题的方式,这意味着使用 Neptune Bulk Loader

    专门针对您的问题,尽管您可能会看到对您所描述的方法的一些优化。从 Gremlin 的角度来看,我想您可以通过结合现有的遍历为每个边提交一个 Gremlin 请求来节省一些成本:

    g.V().has(label, name, foo).fold().
      coalesce(unfold(), 
               addV(label).property(name, foo)).
      property(model, 2).as('source').
      V().has(label, name, bar).fold().
      coalesce(unfold(), 
               addV(label).property(name, bar)).
      property(model, 2).as('target').
      coalesce(inE(edge_label).where(outV().as('source')), 
               addE(edge_label).from('source').to('target')).
      property(model, 2)
    

    我想我是对的 - 未经测试,但希望你明白这一点。基本上,我们只是通过步骤标签引用内存中已经存在的顶点,这样我们就不需要重新查询它们。如果您继续使用 Gremlin 样式的批量加载(例如对边缘进行排序),您也可以尝试其他策略,以便您可以将更多边缘负载批量处理以减少顶点查找的数量并以更动态的方式提交顶点/边缘数据,如所述 @ 987654322@.

    【讨论】:

    • 我有一个类似的用例。我想插入大量顶点。我还考虑了您描述的方式,但最终进行了 3 次遍历: 1. 根据(可能是新的)id 查找所有顶点。 2. 为所有未找到的 id 创建顶点。 3. 更新所有旧顶点。这要快得多。我使用的是 JanusGraph,而不是海王星。
    • 我倾向于以直接回答原始帖子的方式回答 Gremlin 问题,同时提供警告和最佳实践。您很可能会找到适合特定图形数据库提供商的更好方法。我想,根据您的要求,当涉及到 JanusGraph 时,您甚至可能会找到更快的使用 Spark 批量加载的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 2022-12-21
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    • 2016-08-15
    相关资源
    最近更新 更多