質問

REST APIのバッチエンドポイント、約5Kレコード/s(まだ増加している)を介して、それらの間の関係を持つ膨大な量のノードをNEO4Jに挿入する必要があります。

これは24時間365日連続挿入になります。各レコードは1つのノードのみを作成する必要がある場合がありますが、他のノードが2つのノードと1つの関係が作成される場合があります。

手順を変更したり、NEO4Jの設定を変更したりすることで、インサートのパフォーマンスを改善できますか?

これまでの私の進歩:

1.私はしばらくNEO4Jでテストしていましたが、必要なパフォーマンスを得ることができませんでした

テストサーバーボックス:24コア + 32GB RAM

NEO4J 2.0.0-M06スタンドアロンサービスとしてインストールされています。

同じサーバーでJavaアプリケーションを実行している。

REST APIエンドポイント: /db /data /batch(ターゲット: /cypher)

スキーマインデックス、制約、マージ、一意の作成を使用します。

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.私のCypher QueriesとJSONリクエスト

3.1. 1つのレコードが単一ノードの作成を必要とする場合、職務内容は以下のようになります

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

3.2. 1つのレコードが1つの関係を作成する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を混合した)を送信します。

4.パフォーマンスの問題

4.1. 並行性:

/db/data/batch(ターゲット:/cypher)は、スレッドが安全ではないようで、2つ以上の同時スレッドでテストされ、2分分以内にNeo4Jサーバーを下げました。

4.2. 制約とマージすると常に機能するとは限りません。

2つのノードと1つのクエリとの1つの関係を作成する場合(3.2で上記)、魅力のように機能します。しかし、それはいつかcypherexecutionexceptionで失敗し、ノードxxxxの1つがすでにラベルAAAAとプロパティ「bbbbb」= [ccccc]に存在していると述べています。私の理解から、マージは例外を返すのではなく、既に存在する場合はノードを返します。

例外の結果として、バッチ全体が故障し、ロールバックが失敗し、挿入率に影響します。

私はこの問題のためにGitHubで問題を開きました、 https://github.com/neo4j/neo4j/issues/1428

4.3. 制約のあるユニークな作成は、関係の創造に常に機能するとは限りません。

これは同じGitHub問題でも言及されています。

4.4. パフォーマンス:

実際、cypherでバッチを使用する前に、get_or_create(/db/data/index/node/post?uniteness = get_or_create&/db/data/index/relationss/xxxxx?ainisefense = get_or_create)でレガシーインデックスを試しました。

これらのレガシーインデックスエンドポイントの性質により(実際のデータストレージのデータの代わりにインデックスのデータの場所を返す)、バッチ内で使用することはできませんでした(同じバッチで作成されたノードを参照する機能が必要です))

Auto_indexingを有効にし、レガシーインデックスの代わりにデータストレージを直接処理できることはわかっていますが、2.0.0から言及されていますが、スキーマインデックスはレガシーインデックスよりも推奨されるため、Batch + Cypher + Schema Indexアプローチに切り替えることにしました。

ただし、Batch + Cypherを使用すると、1秒あたり約200のジョブの説明しか取得できません。挿入率は、制約とのマージが常に機能していればはるかに高かったでしょう。 /s。また、制約なしでスキーマインデックスを試しましたが、挿入率の点でパフォーマンスがさらに低くなりました。

役に立ちましたか?

解決

2.0を使用すると、トランザクションエンドポイントを使用して、例えばHTTP要求あたり100または1000、トランザクションあたり約30k〜50k(コミットするまで)にステートメントを作成します。

新しいストリーミング、トランザクションエンドポイントの形式については、これを参照してください。

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

また、このような高性能で連続的な挿入エンドポイントについては、埋め込みAPIに対して実行され、1秒あたり10k以上のノードと関係を簡単に挿入できるサーバー拡張機能を作成することを心からお勧めします。ドキュメントについてはこちらをご覧ください。

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

純粋なインサートの場合、暗号は必要ありません。同時性のために、よく知られている(あなたが挿入しているサブグラフごと)ノードでロックして、同時インサートが問題にならないように、あなたはそれを行うことができます tx.acquireWriteLock() または、ノードから存在しないプロパティを削除することにより(REMOVE n.__lock__).

管理されていない拡張機能(ただし、Cypherを使用するもの)を書く別の例については、このプロジェクトをご覧ください。役立つモードもあります(CSVファイルをサーバーエンドポイントに投稿して、行ごとのCypherステートメントを使用して実行されます)。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top