【问题标题】:neo4j update properties on 10 million nodesneo4j 在 1000 万个节点上更新属性
【发布时间】:2016-01-14 19:14:40
【问题描述】:

我使用neo4j java core 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();
}

这里是可运行类

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 内存的 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

【问题讨论】:

    标签: java multithreading neo4j core-api


    【解决方案1】:

    在我看来,有些地方可以改进。

    题外话

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

    性能

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

    • 创建工作
    • 启动线程(其实executor中有pool)
    • 开始交易

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

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

    设置

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

    黑客

    您有 32GB 内存。我可以建议:

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

    仅针对您的情况。如果所有您的数据可以放入 RAM,那么您可以将 cache_type 更改为 hard 以实现此更改目的。 Details.

    配置

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

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

    【讨论】:

    • 感谢您的建议。这是一个非托管服务器扩展。我还考虑了为每个节点创建事务的问题 - 这是我将尝试的第一步,收集一些节点。
    • 我尝试在事务中收集 n 个节点 - 仍然没有提高性能,我还将堆大小设置为 8 GB。在我的情况下,属性“dbms.pagecache.memory”会影响性能吗?
    • 我还发现在线程池中使用 1 或 16 个线程并不重要
    【解决方案2】:

    我发现属性“cache_type=soft”存在问题。我将其设置为“cache_type=none”,执行时间从 30 分钟减少到 2 分钟。在一些更新之后,总是有线程被阻塞大约 30 秒 - 更改此属性有助于避免这些阻塞。我会寻找更详细的解释。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 2020-04-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多