2017-03-16 17 views
1

小さなコンテキスト:当社のアイデンティティビジネスのマスターデータ管理システムとしての可能性のあるNeo4J(初心者ではあるが、他のデータベース技術に経験を積んでいる)特に電子メールアドレスが使用されている場所など、意味のあるものを表現するこれらのノード間の関係を持つアイデンティティ属性(例えば、電子メールアドレス、電話番号、選挙ロールデータなど)のグラフを構築することを目指す。 、または電話番号が登録されている場所。Neo4J Cypher:複数のプロパティの一致とリレーションシップの作成

所望のシステム・プロパティ:私は、私たちにvalubleているいくつかの特定のプロパティには、このシステムをしたいと思います:プロバイダのかなりの数(100以上)からの情報の

  • 高速摂取を、これは長い(時間を排除します)ETLプロセス、短いものは大丈夫です!
  • これはバッチインポーターの使用を排除し、フォールトトレラントクラスターを使用する可能性が最も高く、シャーディングは良いでしょう:)
  • 最終的に30Gレコード/年(〜1000 /秒)、それらを保持し、~100G関係/年の作成と保持、今私たちはこの負荷の1/10を摂取しています。

私は立ち往生しています:Azureの単一ノード、32GB RAM、4コア、非ローカルディスク、Debian 8とNeo4J 3.1.1を試しています。これは、LOAD CSVまたは自家製のJavaとボルトのいずれかを使用して、ほんの10分で、英国の郵便住所ファイル(PAF)を約29Mレコードで摂取し、関連づけています。私はまた、電子メールアドレスデータのテストセット、およそ20Mのレコードを摂取しましたが、関連していませんでした。そして、2つのデータセットの間に対応するポストコード、建物番号、および場合によっては他のフィールドに基づいて関係を構築する必要があります。これは、サイファーを使用するときに物事がはるかに遅い取得する場所であり、ここでは私がこれまでに作成することができた最速のクエリです:

UNWIND {list} AS i 
MATCH(e:DDSEMAIL) WHERE ID(e) = i WITH e 
MATCH(s:SUBBNAME) USING INDEX s:SUBBNAME(SBNA) 
    WHERE upper(e.Building) = s.SBNA WITH e,s 
MATCH(m:MAINFILE) 
    WHERE trim(split(e.Postcode,' ')[0]) = m.OUTC AND 
    trim(split(e.Postcode,' ')[1]) = m.INCO AND 
    right('0000'+e.HouseNo,4) = m.BNUM AND 
    (m)-[:IS_SUBBNAME]->(s) 
CREATE (e)-[r:USED_AT]->(m) 
RETURN COUNT(r); 

インデックスは以下のとおりです。

ON :DDSEMAIL(HouseNo) ONLINE 
ON :DDSEMAIL(Postcode) ONLINE 
ON :DDSEMAIL(Building) ONLINE 
ON :MAINFILE(OUTC)  ONLINE 
ON :MAINFILE(INCO)  ONLINE 
ON :MAINFILE(BNUM)  ONLINE 
ON :SUBBNAME(SBNA)  ONLINE 

{リスト}パラメータがあることに注意してください約20MのDDSEMAILノードをすべて列挙したJavaクライアントからボルトを介して供給され、トランザクション(通常は一度に1000個のID)にバッチ処理されます。

これは、157000 IDのテスト実行で、IDごとに100-200msecsを要し、これは7.3時間かかっており、〜760時間または> 1ヶ月の完全実行時間を示しています。基礎となるマシンは、CPUバウンド(重要なIO待ち時間なし)に見えます。 ..

このクエリのEXPLAINを見てみると

は、何のフルスキャンが存在しない、それは(かつて私は、明示的なインデックスステートメントを含めた)すべてのスキーマのインデックスマッチングですので、私はもっとスピードを見てどこか分かりません

(このプロファイル出力を追加する編集):

PROFILE part 1 PROFILE part 2

これは郵便番号の両方の部分に一致する行(56K)の多くをフィルタリングされていることを示し、再した方が良いかもしれフィルタの入力サイズを小さくするには、これらのフィールドを並べ替えます。 (非常に不公平な)比較として、CSVファイルの両方のデータセットを、C#/ .NETで書かれたカスタムBloomフィルタにプッシュしました。これは、上記と同様のフィールド再フォーマットを実行し、連結して生成しますこれらのキーを一致させます。これにより、すべての29M PAFレコードに対する20Mのすべての電子メールレコードが、私のラップトップの単一のコアに5分以内で畳み込まれました。これは主にIOバウンドでした。

今私は、外部アプリケーションまたはユーザーの手順を使用してレコードの一致を実行し、Cypherを使用してリレーションシップを作成することを検討していますが、これを実行できるはずのよく書かれたクエリエンジンを避けるのは間違っていますそれよりもはるかに早い。

パフォーマンスを改善するにはどうすればよいですか?

+0

物事が改善する可能性がある場所を確認するのに役立つ可能性のある(すべてのプランノードを拡張した後の)説明に、小さなデータセットのクエリのPROFILEまたはEXPLAINのスクリーンショットを追加することができます。 – InverseFalcon

答えて

0

私が正しくリコールすると、別のノードプロパティから供給されたときに比較値(UPPER()やLOWER()やTRIM()など)で変換が行われている場合、 。これらの操作を最初に実行し、エイリアスしてからマッチングを行う必要があります。

インデックスヒントを指定すると、s.SBNAとの一致はインデックスを正しく使用するはずですが、m:MAINFILEの一致するプロパティのいずれかにインデックスがある場合、使用されていない可能性がありますインデックス。

小さなデータセットの古いクエリにこのクエリを比較し、これは違いを作るかどうかを確認するためにテストし、:また

UNWIND {list} AS i 
MATCH(e:DDSEMAIL) WHERE ID(e) = i 
WITH e, upper(e.Building) as SBNA 
MATCH(s:SUBBNAME) 
WHERE s.SBNA = SBNA 
WITH e,s, trim(split(e.Postcode,' ')[0]) as OUTC, 
      trim(split(e.Postcode,' ')[1]) as INCO, 
      right('0000'+e.HouseNo,4) as BNUM 
MATCH(m:MAINFILE) 
WHERE OUTC = m.OUTC AND 
     INCO = m.INCO AND 
     BNUM = m.BNUM AND 
     (m)-[:IS_SUBBNAME]->(s) 
CREATE (e)-[r:USED_AT]->(m) 
RETURN COUNT(r); 

、あなたはPROFILEのスクリーンショットを追加したりするクエリのEXPLAINができればすべての計画ノードを拡張した後の説明は、状況が改善する可能性がある場所を確認するのに役立ちます。

EDIT

あなたはこれらのは良いアイデアかもしれバッチ処理、あなたの説明で述べたように。 APOC手順はapoc.periodic.iterate()です。

クエリに適用できるかどうかを見てみましょう。これを試してみてください:

WITH {list} AS list 
CALL apoc.periodic.iterate(' 
UNWIND {list} as list 
RETURN list 
', ' 
WITH {list} as i 
MATCH(e:DDSEMAIL) WHERE ID(e) = i 
WITH e, upper(e.Building) as SBNA 
MATCH(s:SUBBNAME) 
WHERE s.SBNA = SBNA 
WITH e,s, trim(split(e.Postcode,' ')[0]) as OUTC, 
      trim(split(e.Postcode,' ')[1]) as INCO, 
      right('0000'+e.HouseNo,4) as BNUM 
MATCH(m:MAINFILE) 
WHERE OUTC = m.OUTC AND 
     INCO = m.INCO AND 
     BNUM = m.BNUM AND 
     (m)-[:IS_SUBBNAME]->(s) 
MERGE (e)-[:USED_AT]->(m) 
', {batchSize:1000, iterateList:true, params:{list:list}}) YIELD batches, total, committedOperations, failedOperations, failedBatches, errorMessages 
RETURN batches, total, committedOperations, failedOperations, failedBatches, errorMessages 

は、私たちはバッチ処理クエリから値を返すことができないとして、しかし、作成した関係の合計数を返す犠牲にしなければなりません。

+0

OK @ InverseFalcon、これを試してみましたが、1回の実行でdbヒット数が約半分になり、長いテストになります... – Phlash

+0

残念ながら、最初の900の後にバッファーに当たって、〜1.3sec/IDの速度で数時間ディスクを噛んでいました。私は週末に実行を残すだろうが、これは私がほとんどの時間に直面する可能性があるコールドキャッシュの問題のように見える... – Phlash

+0

真剣に奇妙な、私はWebクライアントを切断し、テストマシンをログオフした画面セッションで走っている)、すべてがはるかに速く走っているようだ...もっと多くの統計は月曜日に! – Phlash

関連する問題