簡體   English   中英

使用REST優化Neo4j中的大批量批量插入

[英]Optimizing high volume batch inserts into Neo4j using REST

我需要通過REST API的Batch端點將大量節點與它們之間的關系插入Neo4j,大約5k記錄/秒(仍在增加)。

這將是24x7的連續插入。 每條記錄可能只需要創建一個節點,但其他記錄可能需要創建兩個節點和一個關系。

我可以通過更改程序或修改Neo4j的設置來提高插入的性能嗎?

我到目前為止的進展:

1.我一直在測試Neo4j,但是我無法獲得所需的性能

測試服務器盒:24核+ 32GB RAM

Neo4j 2.0.0-M06作為獨立服務安裝。

在同一台服務器上運行我的Java應用程序。(Neo4j和Java應用程序將來需要在自己的服務器上運行,因此無法使用嵌入式模式)

REST API端點:/ db / data / batch(target:/ cypher)

使用模式索引,約束,MERGE,CREATE UNIQUE。

2.我的架構:

neo4j-sh (0)$ schema
==> Indexes
==>   ON :REPLY(created_at)   ONLINE                             
==>   ON :REPLY(ids)          ONLINE (for uniqueness constraint) 
==>   ON :REPOST(created_at) ONLINE                             
==>   ON :REPOST(ids)        ONLINE (for uniqueness constraint) 
==>   ON :Post(userId)      ONLINE                             
==>   ON :Post(postId)    ONLINE (for uniqueness constraint) 
==> 
==> Constraints
==>   ON (post:Post) ASSERT post.postId IS UNIQUE
==>   ON (repost:REPOST) ASSERT repost.ids IS UNIQUE
==>   ON (reply:REPLY) ASSERT reply.ids IS UNIQUE

3.我的密碼查詢和JSON請求

3.1。 當一條記錄需要創建單個節點時,作業描述如下所示

{"method" : "POST","to" : "/cypher","body" : {"query" : "MERGE (child:Post {postId:1001, userId:901})"}}

3.2。 當一個記錄需要創建一個關系的兩個節點時,作業描述如下所示

{"method" : "POST","to" : "/cypher","body" : {"query" : "MERGE (parent:Post {postId:1002, userId:902}) MERGE (child:Post {postId:1003, userId:903}) CREATE UNIQUE parent-[relationship:REPOST {ids:'1002_1003', created_at:'Wed Nov 06 14:06:56 AST 2013' }]->child"}}

3.3。 我通常每批發送100份職位描述(3.1和3.2混合),大約需要150~250ms才能完成。

4.性能問題

4.1。 並發:

/ db / data / batch(target:/ cypher)似乎不是線程安全的,使用兩個或多個並發線程進行測試,這使得Neo4j服務器在第二(s)〜分鍾內停止運行。

4.2。 帶約束的MERGE並不總是有效。

當使用單個查詢創建兩個節點和一個關系時(在3.2。中提到),它有時像魅力一樣; 但它有時會因CypherExecutionException失敗並說其中一個Node xxxx已經存在,標簽為aaaa,屬性為“bbbbb”= [ccccc]; 根據我的理解,MERGE不會假設返回任何異常,但如果節點已經存在則返回該節點。

作為例外的結果,整個批次將失敗並回滾,這會影響我的插入率。

我已經在GitHub中為此問題打開了一個問題, https://github.com/neo4j/neo4j/issues/1428

4.3。 使用約束創建獨特並不總是適用於關系創建。

這也在同一個github問題中提到過。

4.4。 性能:

實際上,在我使用cypher批處理之前,我嘗試使用get_or_create進行遺留索引(/ db / data / index / node / Post?uniqueness = get_or_create&/ db / data / index / relationship / XXXXX?uniqueness = get_or_create)

由於這些遺留索引端點的性質(它們返回索引中數據的位置而不是實際數據存儲中數據的位置),因此我無法在批處理中使用它們(需要先前在同一批次中創建的引用節點的功能) )

我知道我可以啟用auto_indexing,直接處理數據存儲而不是遺留索引,但他們從2.0.0中提到,建議使用模式索引而不是傳統索引,所以我決定切換到批處理+密碼+模式索引方法。

但是,對於批處理+密碼,我每秒只能獲得大約200個作業描述插入率,如果帶有約束的MERGE總是有效的話會更高,假設大約600~800 / s,但它仍然遠低於5k /秒。 我也嘗試了沒有任何約束的模式索引,它在插入率方面的表現甚至更低。

使用2.0,我將使用事務端點批量創建語句,例如每個http請求100或1000,每個事務大約30k-50k(直到你提交)。

有關新的流式事務端點的格式,請參閱此處:

http://docs.neo4j.org/chunked/milestone/rest-api-transactional.html

此外,對於如此高性能的連續插入端點,我衷心建議編寫一個服務器擴展,該擴展將針對嵌入式API運行,並且每秒可以輕松插入10k或更多節點和關系,請參閱此處的文檔:

http://docs.neo4j.org/chunked/milestone/server-unmanaged-extensions.html

對於純插件,您不需要Cypher。 對於並發性,只需鎖定一個眾所周知的(每個要插入的子圖)節點,以便並發插入沒有問題,您可以使用tx.acquireWriteLock()或從節點中刪除不存在的屬性( REMOVE n.__lock__ )。

有關編寫非托管擴展(但使用密碼的擴展)的另一個示例,請查看此項目。 它甚至有一個可以幫助你的模式(將CSV文件發布到服務器端點,每行使用一個cypher語句執行)。

https://github.com/jexp/cypher-rs

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM