2017-06-29 2 views
-4

異なるサイズのデータ​​セット、100万〜10億のエッジ(頂点あたり10個のエッジ)でJavaクエリをテストしています。 クエリは多くのデータ、対応するエッジを持つ10〜20の頂点を返しませんが、データセット全体をスキャンする必要があります。neo4j java query DBで巨大なスローダウン> 32G

データベースのサイズが32ギガバイトを超えると、パフォーマンスが大幅に低下することがあります。 私は96GにJavaのヒープサイズを変更し、ガベージコレクタのオプションでプレイ(保持-XX:+ UseG1GC最も向上オプションとして) 良好な結果を得るが、私はまだ性能に大きなディップを取得します

100Mエッジをデータベースは7.5Gです:クエリは12分を要します 250Mエッジ、データベースは19G:35分 500Mエッジ、データベースは38G:-XX:+ UseG1GCを使用して12時間 1Bエッジ、データベースは76G:-XXなしの51時間: + UseG1GC

さらに、500万回と10億回のテストでは、操作の大部分がシステム操作60%対ユーザー操作40%(上位のlinuxコマンドから)であることがわかります。小さなテストを実行すると、操作の100%はユーザーの操作です。

neo4jのentreprise版のJava GCの改善は、より小さいものと同じ割合で大きなデータセットクエリのパフォーマンスを引き出すのに十分なほど重要ですか? 大規模なデータセットクエリのパフォーマンスを向上させるためにできることはありますか?

TKS

私は32コア244 RAMの仮想サーバー上のすべてのこれらのテストを実行します。

また、私はページキャッシュのサイズを増やそうとしましたが、改善は見られませんでした。

ユースケース: 私はデータのパターンを検索しています。クエリはすべてのデータセットをスキャンして、特別なパターンの関係を持つ4つまたは5つのノードを検索します。

クエリはスレッドで実行されるため、32コアはすべて同時に実行されます。

私は変更しようとしました: - スレッド あたりのノード数 - ヒープサイズ - キャッシュサイズ - GCオプション

ではなく、多くの改善を。 これはJavaの制限ですか? ありがとう

+2

は、データモデルと使用例を示し、いくつかのサンプルコード。それ以外の場合は、十分な情報がありません。 – cybersam

+0

はサイバーサムに同意します。また、ハードウェアはデータセットのサイズに対応していますか? –

+0

照会を調整するにはEXPLAIN、PROFILEを参照してください(または必要に応じて索引を作成してください) –

答えて

0

あなたはJVMヒープを設定しようとしていますが、page cacheでも同じことをしていますか?

JVMのヒープは、すべてのトランザクション処理を格納するために使用され、ページキャッシュはディスクI/Oを回避するためにグラフデータをメモリに格納するために使用されます。

私は(それはまだ行っていない場合)は、ページこの文書を見てみることをお勧め:12Goは、いくつかの大きなのGCにつながることができ、そのためあまりパフォーマンスするよりも高いJavaヒープを持っているためにhttps://neo4j.com/docs/operations-manual/3.2/performance/#memory-tuning

を。

EEにはいくつかの改善点がありますが、具体的なケースではギャップが重要ではないと思います。

最後に、すべてのデータを必要とするクエリを使用することは、すべてのデータベースシステムで悪い考えです。私はユースケースについて興味があります。あなたはそれを説明できますか?

@Jeromeと同様に、クエリを調整する必要があります。

乾杯。

0

クエリのチューニングは、小規模なデータセット(最大250万の関係)で非常に効率的であり、大きくなると指数関数的に遅くなるため、スケーラビリティの問題を説明しているとは思えません。 Javaのメモリ管理は役割を果たす必要がありますが、私はそれを回避する方法を見つけることができません。

クエリーでは、速度が増加する三角形が検索され、最大速度と最小速度はマージン(50)内になければなりません。グラフは、関係(速度)に1つのパラメータしか持たないように単純化されています。 (a) - [d] - >(b) - [e] - >(c) - [f] - >(a)d.speed < = e.speed AND e.speed < = f.speed AND(f.speed-d.speed)< = 50 return a、b、c。

Javaのクエリーは、スレッド内の各ノード上で実行します。

void findTriangleV1(Node n){ 
    Iterable<Relationship> Level1 = n.getRelationships(Direction.OUTGOING); 
    for(Relationship r1 : Level1) { 
     if (r1.getEndNodeId() != n.getId()){ 
      Integer tsr1 = (Integer)r1.getProperty("speed"); 
      Iterable<Relationship> Level2 = r1.getEndNode().getRelationships(Direction.OUTGOING); 
      for(Relationship r2 : Level2) { 
       if (r1.getEndNodeId() != r2.getEndNodeId()){ 
        Integer tsr2 = (Integer)r2.getProperty("speed");         
        if ((tsr2 >= tsr1) && (tsr2 - tsr1 <= limit)){ 
         Iterable<Relationship> Level3 = r2.getEndNode().getRelationships(Direction.OUTGOING); 
         for(Relationship r3 : Level3) { 
          if (r3.getEndNodeId() == n.getId()){ 
           Integer tsr3 = (Integer)r3.getProperty("speed"); 
           if ((tsr3 >= tsr2) && (tsr3 - tsr1 <= limit)){ 
            System.out.print("\nV1 FOUND ONE ["+ n.getId() +" - "+ r1.getEndNodeId()+" - "+ r2.getEndNodeId()+"] & ");  
            System.out.print("speed ["+ tsr1 +" - "+ tsr2+" - "+ tsr3+"] \n"); 
           }        
          } 
         } 
        }     
       } 
      } 
     } 
    } 
    return; 
}