0

插入 2000 个节点消耗 10000ms。这是我正在尝试的代码:

package org.demo.neo4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;

public class Main {

    private GraphDatabaseService neo = Noe4jUtils.getInstance();
    private static ExecutorService pool = Executors.newFixedThreadPool(4);
    private static Semaphore semaphore = new Semaphore(4);

    public static void main(String[] args) {
        Main main = new Main();
        main.insert();
    }

    private void insert() {
        for (int i = 0; i < 1000; i++) {
            try {
                semaphore.acquire();
                String refName = "REF-" + i;
                pool.execute(new InsertTask(refName, 100000));
            } catch (InterruptedException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void insertRef(String refName, int num) {
        Node rootNode = neo.getReferenceNode();
        RelationshipType rt = DynamicRelationshipType.withName(refName);
        Relationship r = rootNode.getSingleRelationship(rt, Direction.OUTGOING);
        Node refNode;
        if (null == r) {
            refNode = createRef(rootNode, rt);
        } else {
            refNode = r.getOtherNode(rootNode);
        }
        int size = 2000;
        int cnt = num / size;
        if ((num % size) != 0) {
            cnt = cnt + 1;
        }
        int index = 0;
        for (int i = 0; i < cnt; i++) {
            long l1 = System.currentTimeMillis();
            Transaction tx = neo.beginTx();
            try {
                int tmpNum = 0;
                for (int j = 0; j < size; j++) {
                    index++;
                    if (index > num) {
                        break;
                    }
                    tmpNum++;
                    createNode(refNode);
                }
                tx.success();
                System.out.println("insert " + tmpNum + " node.");
            } finally {
                tx.finish();
                l1 = System.currentTimeMillis() - l1;
                System.out.println("consume " + l1 + " ms.");
            }
        }
    }

    private Node createRef(Node node, RelationshipType rt) {
        Transaction tx = neo.beginTx();
        try {
            Node tmpNode = node.getGraphDatabase().createNode();
            node.createRelationshipTo(tmpNode, rt);
            tx.success();
            return tmpNode;
        } finally {
            tx.finish();
        }
    }

    private Node createNode(Node node) {
        RelationshipType rt = DynamicRelationshipType.withName("LINK");
        Node tmpNode = node.getGraphDatabase().createNode();
        node.createRelationshipTo(tmpNode, rt);
        for (int i = 0; i < 100; i++) {
            tmpNode.setProperty("key" + i, i);
        }
        return node;
    }

    class InsertTask implements Runnable {

        public InsertTask(String refName, int num) {
            this.refName = refName;
            this.num = num;
        }
        private String refName;
        private int num;

        @Override
        public void run() {
            try {
                insertRef(refName, num);
            } finally {
                semaphore.release();
            }
        }
    } }
4

2 回答 2

2

创建这些小交易的目的是什么?neo4j 中的每个事务都会强制将逻辑日志写入磁盘,因此基本上所有时间都在等待磁盘刷新。因此,多线程并没有太大帮助,相反它可能会更慢。尝试在每个事务中将许多操作组合在一起并拥有一个线程。

顺便说一句,您的用例是什么?

于 2012-07-05T19:24:18.290 回答
-1

你是在 Linux 下的 ext4 文件系统上运行它吗?

如果您想用一点事务安全性换取 10-15 倍更好的写入性能,请尝试使用 barrier=0 选项,如下所述:http: //structr.org/blog/neo4j-performance-on-ext4

于 2013-12-11T00:46:52.310 回答