neo4j更新了1000万个节点上的属性

时间:2015-10-16 06:12:23

标签: java multithreading neo4j core-api

我使用neo4j java核心api并希望更新1000万个节点。 我认为用多线程做它会更好,但性能不是那么好(设置属性需要35分钟)。

解释:每个节点" Person"至少有一种关系" POINTSREL"到了" Point"节点,具有属性" Points"。我想总结来自" Point"节点并将其设置为" Person"节点。

这是我的代码:

Transaction transaction = service.beginTx();
ResourceIterator<Node> iterator = service.findNodes(Labels.person);
transaction.success();
transaction.close();

ExecutorService executor = Executors.newFixedThreadPool(5);

while(iterator.hasNext()){
    executor.execute(new MyJob(iterator.next()));
}

//wait until all threads are done
executor.shutdown();

try {
    executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
    e.printStackTrace();
}

这里是runnable类

private class MyJob implements Runnable {

    private Node node;

    /* collect useful parameters in the constructor */
    public MyJob(Node node) {
        this.node = node;
    }

    public void run() {
        Transaction transaction = service.beginTx();
        Iterable<org.neo4j.graphdb.Relationship> rel = this.node.getRelationships(RelationType.POINTSREL, Direction.OUTGOING);

        double sum = 0;
        for(org.neo4j.graphdb.Relationship entry : rel){
            try{
                sum += (Double)entry.getEndNode().getProperty("Points");
            } catch(Exception e){
                e.printStackTrace();
            }
        }
        this.node.setProperty("Sum", sum);

        transaction.success();
        transaction.close();
    }
}

有更好(更快)的方法吗?

关于我的设置: 具有8个CPU和32GB RAM的AWS实例

的Neo4j-wrapper.conf

# Java Heap Size: by default the Java heap size is dynamically
# calculated based on available system resources.
# Uncomment these lines to set specific initial and maximum
# heap size in MB.
wrapper.java.initmemory=16000
wrapper.java.maxmemory=16000

neo4j.properties

# The type of cache to use for nodes and relationships.
cache_type=soft
cache.memory_ratio=30.0
neostore.nodestore.db.mapped_memory=2G
neostore.relationshipstore.db.mapped_memory=7G
neostore.propertystore.db.mapped_memory=2G
neostore.propertystore.db.strings.mapped_memory=2G
neostore.propertystore.db.arrays.mapped_memory=512M

2 个答案:

答案 0 :(得分:1)

从我的角度来看,有些东西可以改进。

Offtopic

如果您使用的是Java 7(或更高版本),请考虑使用try with resource来处理事务。它可以防止您出错。

效果

首先 - 批处理。目前你是:

  • 创建工作
  • 启动线程(实际上,执行程序中有池)
  • 开始交易

对于每个节点。您应该考虑在批次中进行更新。这意味着你应该:

  • 收集N个节点(例如N = 1000)
  • N个节点
  • 创建单个作业
  • 在作业中创建单个交易
  • 更新该事务中的N个节点
  • 关闭交易

设置

你有8个CPU。这意味着您可以创建更大的线程池。我认为Executors.newFixedThreadPool(16)会好的。

黑客

你有32GB的RAM。我可以建议:

  • 将Java堆大小减少到8GB。根据我的经验,大堆大小可能导致大的GC暂停和性能下降
  • 增加映射内存大小。只是为了确保可以在缓存中保存更多数据。

仅适用于您的情况。如果所有您的数据可以放入RAM,那么您可以将cache_type更改为hard以进行此更改。 Details

配置

正如您所说 - 您正在使用Core API。这是Embedded图形数据库还是服务器extension

如果这是Embedded图形数据库 - 您应该验证数据库设置是否应用于创建的实例。

答案 1 :(得分:0)

我发现除其他外,该物业存在问题&#34; cache_type = soft&#34;。我把它设置为&#34; cache_type = none&#34;并且执行的持续时间从30分钟减少到2分钟。经过一些更新后,总会有线程被阻塞大约30秒 - 更改此属性有助于避免这些阻塞。我将寻找更详细的解释。