[英]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語句執行)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.