根据公认的答案,一个简单的并行化得到了足够的改进,这个操作不再是最关键的时间
为了将来参考,这个:
g.V().hasLabel(LABEL_INTERMEDIATE_COLUMN).not(inE(EDGE_DEPEND)).drop().iterate();
现在是这样的:
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 个也可能太多(总是有 1 个或更多线程处于等待状态)——尽管我确实得到了一个运行 3 个线程的转储!