2012-07-05 109 views
0

插入2000個節點消耗10000ms。這是我正在嘗試的代碼:插入節點時neo4j性能問題

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(); 
      } 
     } 
    } } 

回答

2

創建這些小型交易的目的是什麼? neo4j中的每個事務都強制將邏輯日誌記錄到磁盤,所以基本上所有的時間都花在等待磁盤刷新。因此,多線程並沒有太多的幫助,相反它可能會變慢。嘗試將許多操作分組在一起,而不是在每個事務中,並有一個線程。

順便說一句你的用例是什麼?