2016-10-17 18 views
0

次のグラフ構造またはクエリのいずれかを改善してパフォーマンスを向上させるための提案はありますか?理想的には、私はこれをサブ1sに持っていきたいと思います。今すぐ最高の私は約2Mのノードと10Mのrels以上7MのDBのヒットで〜8Sを得ることができます。複数のリレーションシップまたは複数のラベルを持つ一意のノード間での集計の実行

私は

(co:Company)<-[:HAS_PROVIDER]-(c:Customer)-[:HAS_CLAIM]->(c:Claim)

  • 各請求項は、「量」とは、各企業が名前を持って
  • いわゆる「直接」のブールプロパティだけでなく、プロパティを持つ構造をグラフ持っ
  • お客様は複数のクレームを持つことができますが、会社は1つだけです

私はショーのことができるようにするには、NT:

  • 個別の会社名の直接の会社真=直接請求の
  • 量の合計真=直接請求のための
  • 数について
  • 顧客数達成するために=虚偽の主張
  • 直接=虚偽の請求額の合計

これは、私は2つのアプローチを使用しました:a)請求項ために顧客からの関係を作成し

どこダイレクト=真のように:IS_DIRECTと直接= falseのように:IS_INDIRECT

B)として、各ダイレクト=真の主張をラベル:DirectClaimノードおよびdirect = falseクレーム:InDirectClaimノード

(a)を使用すると、rels TYPEのフィルタで会社名、顧客数、サイズ(IS_DIRECT)およびサイズ(IS_INDIRECT)を取得できます。ただし、抽出、フィルター、組み合わせの組み合わせを使用して合計(量)を取得すると、構成に関係なくタイムアウトになります。

使用して(b)は動作しますが、10秒

EDIT〜とります。(a)のように見えるため

クエリ

MATCH (co:Company)<-[:HAS_PROVIDER]-(c)-[r:IS_DIRECT|IS_INDIRECT]->(cl) 
WITH distinct co, collect(r) as rels, count (distinct c) as cntc, collect(mc) as claims 
WITH co, cntc, 
size(filter(r in rels WHERE TYPE(r) = 'IS_DIRECT')) as dcls, 
size(filter(r in rels WHERE TYPE(r) = 'IS_INDIRECT')) as indcls, 
REDUCE 
    (s = {dclsamt: 0, indclsamt: 0}, x IN claims | 
    CASE WHEN x.direct 
    THEN {dclsamt: s.dclsamt + x.amount, indclsamt: s.indclsamt} 
    ELSE {dclsamt: s.dclsamt, indclsamt: s.indclsamt + x.amount} 
    END) 
    AS data 
RETURN co.name as name,cntc, dcls,indcls, data 
ORDER BY dcls desc 

(これを@cybersamするhattipでは今〜6Sです) (b)のクエリは次のようになります。

MATCH (co:Company)<-[:HAS_PROVIDER]-(c)-[:HAS_CLAIM]->(cl) 
WITH distinct co, count (distinct c) as cntc, COLLECT(cl) as cls 
WITH co,cntc, 
FILTER(n in cls WHERE 'DirectClaim' IN IN LABELS(n)) as dcls, 
FILTER(n in cls WHERE 'InDirectClaim' IN LABELS(n)) as indcls 
WITH co,cntc, size(dcls) as dclsct, size(indcls) as indclsct, 
REDUCE(s = 0 , x IN dcls | s + x.amount) as dclsamt, 
REDUCE(s = 0 , x IN indcls | s + x.amount) as indclsamt 
RETURN co.name as name, cntc, dclsct, dclsamt, indclsct, indclsamt 
+0

aとbの両方のアプローチで現在使用しているクエリを提供できますか? – InverseFalcon

+0

@InverseFalconがクエリを追加しました – gmjordan

答えて

2

余分なデータを追加する必要はありませんbels)をデータモデルに追加します。

このクエリは、(ttrue量の和である、とtctrue量のカウントで、返さdataマップで、同様にffcのために)あなたが望む結果を返すする1つの方法を示しています

MATCH (co:Company)<-[:HAS_PROVIDER]-(cu:Customer)-[:HAS_CLAIM]->(cl:Claim) 
WITH co.name as comp_name, COUNT(DISTINCT cu) AS cust_count, 
    REDUCE(s = {t: 0, tc: 0, f: 0, fc: 0}, x IN COLLECT(cl) | 
    CASE WHEN x.direct 
     THEN {t: s.t + x.amount, tc: s.tc + 1, f: s.f, fc: s.fc} 
     ELSE {t: s.t, tc: s.tc, f: s.f + x.amount, fc: s.fc + 1} 
    END) AS data 
RETURN comp_name, cust_count, data 
+0

このクエリはこれまでのところ最も高速です。 〜6sローカル、〜10sリモートインスタンス – gmjordan

1

あなたの現在のデータモデルは、必要な結果を生成するのに十分です。

MATCH (co:Company)<-[:HAS_PROVIDER]-(cust:Customer)-[:HAS_CLAIM]->(claim:Claim) 
WITH co, COUNT(DISTINCT cust) AS custs, COLLECT(DISTINCT claim) AS claims 
WITH co, 
custs, 
[x IN claims WHERE x.direct|x.amount] AS direct_amts, 
[x IN claims WHERE NOT x.direct|x.amount] AS indirect_amts 
RETURN co, 
custs, 
SIZE(direct_amts) AS direct_count, 
REDUCE(s=0, x IN direct_amts| s+x) AS direct_amt_total, 
SIZE(indirect_amts) AS indirect_count, 
REDUCE(s=0, x IN indirect_amts| s+x) AS indirect_amt_total 

あなたは本当にスピードが必要な場合は、:Claim(direct):Claim(amount)にインデックスを持っていることを確認すると、これは本当に悲鳴ます。また、ブール値のプロパティを2番目のラベル((claim:Claim:Direct))に変更すると、インデックスを自分で保存できます。

更新:あなたが引用している内容に基づいて、改善の唯一の道はあなたの使用プロファイルに基づいて行われます。このグラフが「生きている」継続的に更新される場合は、:Claimを追加、削除、または変更するたびに、合計と合計の合計を:Customerノードにキャッシュすることができます。それがグラフの輝きです。データベースのサブセットに触れる頻繁ではないクエリです。したがって、あなたがクレームに何かをしたときに、対応する:Customerのためにあなたの集計を再実行し、結果をのプロパティとして保存してから、あなたの大きなレポートでは、これらのプロパティを(より少ない数の):Customerノードから直接取得してください。

+0

ありがとうございます。あなたの2番目の質問は私が必要としていることを記述しており、私はいくつかの前の試みで1つの抽出/フィルターを使用しました。また、「直接」のインデックスを追加しました 参考までに、元の質問に「ベスト」クエリを追加しました。 これらのクエリはすべてまだ〜7秒以内です – gmjordan

関連する問題