首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提高去除TinkerGraph顶点的性能

提高去除TinkerGraph顶点的性能
EN

Stack Overflow用户
提问于 2021-06-19 01:06:12
回答 2查看 261关注 0票数 0

我有一个带有600k顶点和950k边的图950k。经过一些处理后,我需要使用以下查询清理350k+顶点:

代码语言:javascript
复制
g.V().hasLabel(LABEL_INTERMEDIATE_COLUMN).not(inE(EDGE_DEPEND)).drop().iterate();

尽管我排除了没有“依赖”边的顶点,但它们仍然与其他边相连。

使用Java,tinkerpop/tinkergraph 3.4.6。

目前,需要大约45分钟来删除所有这些顶点。

我做了一个java分析,结果显示73%的时间花在TinkerVertex.remove方法上,其余的时间在ExpandableStepIterator.next中。

有“散装滴”之类的东西吗?JanusGraph或其他图形提供程序会更快吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-06-19 11:05:38

不太可能有比TinkerGraph更快的图形,因为TinkerGraph是一个纯内存实现。您可能会发现使用该内存的效率更高,比如OverflowDB,它最初是从TinkerGraph分叉而来的,但我不知道它是否会使这个特定的查询更快。

TinkerGraph,以及我所知道的任何一个图表,都有一个经过过滤的“大容量下降”操作。

这里的"not“样式的全局查询简单、昂贵,因为您必须触摸图形的很大一部分。当然,我感到有点惊讶的是,TinkerGraph花了这么长的时间才得到一个小于一百万条边的图。当你做你的个人资料时,你没有提到你是否经历了大量的GC。也许这是个问题?如果是这样的话,我会尝试调整您的JVM内存配置--也许您只需要一个更大的-Xmx值或类似这样的简单值。

从查询的角度来看,您可以尝试倒转遍历的not()部分,以积极地查找要删除的内容。它可能导致读取的查询不那么简洁,但可能会加快速度,但另一方面,您仍在尝试删除50%的数据,因此成本可能不只是查找要删除的顶点。

另一个想法是尝试并行化drop()。您可能会遇到并发错误,因此需要重试策略,但是可以考虑使用Iterator of g.V().hasLabel(LABEL_INTERMEDIATE_COLUMN).not(inE(EDGE_DEPEND)),然后将对每个(或多个) Vertex.remove()的调用委托给一个单独的工作线程。

票数 2
EN

Stack Overflow用户

发布于 2021-06-21 21:34:04

基于公认的答案,一个简单的并行化改进得足够多,使这个操作不再是最关键的时间。

供日后参考:

代码语言:javascript
复制
g.V().hasLabel(LABEL_INTERMEDIATE_COLUMN).not(inE(EDGE_DEPEND)).drop().iterate(); 

现在是这样的:

代码语言:javascript
复制
ExecutorService executor = Executors.newFixedThreadPool(4);
int iterator = 0;
final int batchsize = 10000;
Long count = g.V().hasLabel(LABEL_INTERMEDIATE_COLUMN).not(inE(EDGE_DEPEND)).count().next();
List<Callable<Object>> callableList = new ArrayList<Callable<Object>>();

// splitting current set into tasks to be executed in para
while (iterator * batchsize < count) {
    final Set<Object> vSet =  g.V().hasLabel(LABEL_INTERMEDIATE_COLUMN).not(inE(EDGE_DEPEND)).skip(iterator * batchsize).limit(batchsize).id().toSet();
    callableList.add(() -> g.V(vSet).drop().iterate());
    iterator++;
}
List<Future<Object>> results = executor.invokeAll(callableList);

经过一些测试后,我决定将迭代保留在一个线程中。这样,分布式任务实际上是相互独立的(例如:一个任务完成不会影响其他任务查询)。

请记住,实际删除仍然是单线程,因为顶点节点映射修改在并发访问锁之后。

结果是增加线程不会得到更好的结果(亲自尝试了8)。基于某些线程转储,即使是4也可能太多(总是有一个或多个线程处于等待状态)--尽管我确实得到了一个具有3个线程运行的转储!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68042799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档