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。また、制約なしでスキーマインデックスを試しましたが、挿入率の点でパフォーマンスがさらに低くなりました。