2012-03-05 30 views
5

tôi muốn lưu trữ một số dữ liệu trong cơ sở dữ liệu neo4j của mình. tôi sử dụng spring-data-neo4j cho điều đó.phương pháp lưu CRUDRepository là rất chậm?

mã của tôi là như sau:

for (int i = 0; i < newRisks.size(); i++) { 
     myRepository.save(newRisks.get(i)); 
     System.out.println("saved " + newRisks.get(i).name); 
    } 

My newRisks mảng chứa khoảng 60000 đối tượng và 60000 cạnh. Mỗi nút và cạnh có một thuộc tính. Thời gian của vòng lặp này là khoảng 15 - 20 phút, điều này có bình thường không? Tôi đã sử dụng Java VisualVM để tìm kiếm một số tắc nghẽn, nhưng mức sử dụng CPU trung bình của tôi là 10 - 25% (trong số 4 lõi) và heap của tôi nhỏ hơn một nửa.

Có bất kỳ tùy chọn nào để tăng cường hoạt động này?


EDIT: thêm là, trên cuộc gọi đầu tiên của myRepository.save(newRisks.get(i)); JVM rơi assleep fpr một vài phút trước khi ra đầu tiên được đến

Second EDIT:

Lớp rủi ro:

@NodeEntity 
public class Risk { 
    //... 
    @Indexed 
    public String name; 

    @RelatedTo(type = "CHILD", direction = Direction.OUTGOING) 
    Set<Risk> risk = new HashSet<Risk>(); 

    public void addChild(Risk child) { 
     risk.add(child); 
    } 

    //... 
} 

Tạo rủi ro:

@Autowired 
private Repository myRepository; 

@Transactional 
public Collection<Risk> makeSomeRisks() { 

    ArrayList<Risk> newRisks = new ArrayList<Risk>(); 

    newRisks.add(new Risk("Root")); 

    for (int i = 0; i < 60000; i++) { 
     Risk risk = new Risk("risk " + (i + 1)); 
     newRisks.get(0).addChild(risk); 
     newRisks.add(risk); 
    } 

    for (int i = 0; i < newRisks.size(); i++) { 
     myRepository.save(newRisks.get(i)); 
    } 

    return newRisks; 
} 
+0

Theo [tài liệu] (http://static.springsource.org/spring-data/data-neo4j/docs/2.0.0.RC1/api/org/springframework/data/neo4j/repository/CRUDRepository. html), CRUDRepository.save có thể lấy Iterable làm đối số. Tại sao không chỉ myRepository.save (newRisks)? – Thomas

+0

tôi đã thử điều này và nó cũng hoạt động. nhưng, nó không nhanh hơn. vì vậy tôi có thể thấy, anh ta không chết ^^ – hilbert

+0

bạn có thể hiển thị cấu trúc của lớp của bạn và bất kỳ tổ chức nút nào và các thực thể quan hệ mà nó đề cập đến không. Và phương pháp xây dựng các trường hợp Rủi ro của bạn? –

Trả lời

5

Vấn đề ở đây là bạn đang thực hiện chèn hàng loạt với một API không dành cho điều đó.

Bạn tạo ra Rủi ro và 60 nghìn trẻ em, trước tiên bạn lưu gốc cũng giữ 60 nghìn trẻ em cùng một lúc (và tạo mối quan hệ). Đó là lý do tại sao lần đầu tiên tiết kiệm rất lâu. Và sau đó bạn cứu trẻ em một lần nữa.

Có một số giải pháp để tăng tốc với SDN.

  1. không sử dụng phương pháp thu thập để chèn hàng loạt, duy trì cả người tham gia và sử dụng template.createRelationshipBetween (root, child, "CHILD", false);

  2. tồn những đứa trẻ đầu tiên sau đó thêm tất cả các trẻ em tiếp tục tồn tại đến đối tượng gốc và tồn tại mà

  3. Như bạn đã làm, sử dụng API Neo4j-Core nhưng gọi template.postEntityCreation (nút, Risk.class) để bạn có thể truy cập các thực thể thông qua SDN.Sau đó, bạn cũng phải lập chỉ mục các thực thể của riêng bạn (db.index.forNodes ("Risk"). Thêm (node, "name", name);) (hoặc sử dụng chỉ mục tự động neo4j core-api, nhưng đó không phải là tương thích với SDN).

  4. Bất kể với lõi-api hoặc SDN bạn nên sử dụng tx-kích thước khoảng 10-20k nút/rels for best performance

+0

cảm ơn bạn đã đúng. Lần đầu tiên tôi chỉ cần lưu gốc, nó chỉ mất 6 phút. Có lẽ sau này tôi phải thử các giải pháp khác mà bạn đề xuất. – hilbert

1

Việc chèn vào cơ sở dữ liệu của bạn (ngoài Java) có cùng độ trễ hoặc đây có phải là sự cố chỉ thông qua dữ liệu xuân không?

+0

ý tưởng hay, nhưng làm cách nào tôi có thể chèn số ghi chú này ra khỏi java? tôi không muốn dùng một ngôn ngữ lập trình khác. Một ý tưởng khác: tôi có thể thử sử dụng api neo4j tiêu chuẩn, không phải spring-data-neo4j. – hilbert

+0

Chỉ cần kích hoạt câu lệnh chèn trong trình soạn thảo SQL của bạn. Điều này sẽ kiểm tra tốc độ của cơ sở dữ liệu, bên ngoài bất kỳ ngôn ngữ lập trình nào. – abehrens

+0

một cơ sở dữ liệu noSQL của nó, nhưng tôi đã thử nó với api java natic cho neo4j, thats nhanh hơn – hilbert

5

Tôi nghĩ rằng tôi đã tìm thấy một giải pháp:

tôi đã cố gắng chèn tương tự sử dụng các Nativ neo4j java API:

GraphDatabaseService graphDb; 
Node firstNode; 
Node secondNode; 
Relationship relationship; 

graphDb = new EmbeddedGraphDatabase(DB_PATH); 
Transaction tx = graphDb.beginTx(); 

try { 
    firstNode = graphDb.createNode(); 
    firstNode.setProperty("name", "Root"); 

    for (int i = 0; i < 60000; i++) { 
     secondNode = graphDb.createNode(); 
     secondNode.setProperty("name", "risk " + (i+1)); 

     relationship = firstNode.createRelationshipTo(secondNode, RelTypes.CHILD); 
    } 
    tx.success(); 
} 
finally { 
    tx.finish(); 
    graphDb.shutdown(); 
} 

kết quả: sau khi một số sconds, cơ sở dữ liệu được làm đầy với rủi ro .

Có thể các phản xạ làm chậm thường trình này với spring-data-neo4j. @Michael Hunger nói rằng mọi thứ như vậy trong cuốn sách của mình là GoodRelationships, cảm ơn vì mẹo đó.

+0

này đã lưu ngày của tôi! nhiều đánh giá cao, cảm ơn. – jarandaf

1

tôi phải đối mặt với vấn đề tương tự như OP. Thực sự hữu ích trong trường hợp của tôi là thay đổi cách sử dụng Neo4j từ máy chủ từ xa sang chế độ được nhúng. Ví dụ về việc sử dụng SDN được nhúng có thể được tìm thấy here.