1

AWS dynamoDB ローカル実装を 16GB マシンのストレージ バックエンドとして使用して、titan 1.0 を使用しています。私の使用例では、頂点とエッジを 120K のオーダーで定期的に含むグラフを生成します。メモリ内に新しいグラフを生成するたびに、DB に保存されているグラフをチェックし、(i) 存在しない頂点/エッジを追加するか、(ii) 既に存在する場合はプロパティを更新します (存在は「ラベル」によって決定されます)。および「値」属性)。'Value' プロパティがインデックス化されていることに注意してください。トランザクションは 500 個の頂点のバッチでコミットされます。

問題:新しいグラフを処理するたびに、このプロセスが遅くなることがわかりました (最初のグラフは最初に空のデータベースで 45 分で終了し、2 番目は 2.5 時間、3 番目は 3.5 時間、4 番目は 6 時間、5 番目は 10 時間など) )。実際、特定のグラフを処理するとき、開始時はかなり高速ですが、徐々に遅くなります (最初のバッチは 2 ~ 4 秒かかり、その後、500 ノードの同じバッチ サイズで数百秒に増加します。バッチには 1000 ~ 2000 秒かかります)。これは処理時間だけです (以下のアプローチを参照)。コミットには常に 8 ~ 10 秒かかります。jvm ヒープ サイズを 10G に設定しましたが、アプリが実行されているときに、最終的にすべてを使い果たしていることに気付きました。

質問:この動作は予期されたものですか? ここで何かが間違っているようです(私の設定/アプローチのどちらかですか?)。どんな助けや提案も大歓迎です。

アプローチ:

  • インメモリ グラフのルート ノードから開始して、すべての子ノードを取得し、キューを維持します。
  • 子ノードごとに、DB に存在するかどうかを確認し、存在しない場合は新しいノードを作成し、いくつかのプロパティを更新します。

    Vertex dbVertex = dbgraph.traversal().V()
            .has(currentVertexInMem.label(), "Value",
                    (String) currentVertexInMem.value("Value"))
            .tryNext()
            .orElseGet(() -> createVertex(dbgraph, currentVertexInMem));
    
    if (dbVertex != null) {
        // Update Properties
        updateVertexProperties(dbgraph, currentVertexInMem, dbVertex);
    }
    
    // Add edge if necessary
    if (parentDBVertex != null) {
        GraphTraversal<Vertex, Edge> edgeIt = graph.traversal().V(parentDBVertex).outE()
                .has("EdgeProperty1", eProperty1) // eProperty1 is String input parameter
                .has("EdgeProperty2", eProperty2); // eProperty2 is Long input parameter
    
        Boolean doCreateEdge = true;
        Edge e = null;
        while (edgeIt.hasNext()) {
            e = edgeIt.next();
            if (e.inVertex().equals(dbVertex)) {
                doCreateEdge = false;
                break;
            }
    
        if (doCreateEdge) {
            e = parentDBVertex.addEdge("EdgeLabel", dbVertex, "EdgeProperty1", eProperty1, "EdgeProperty2", eProperty2);
        } 
        e = null;
        it = null;
    }
    
    ...
    
    if ((processedVertexCount.get() % 500 == 0) 
         || processedVertexCount.get() == verticesToProcess.get()) {                            
        graph.tx().commit();
    }
    

関数の作成:

public static Vertex createVertex(Graph graph, Vertex clientVertex) {
    Vertex newVertex = null; 
    switch (clientVertex.label()) {
    case "Label 1":
        newVertex = graph.addVertex(T.label, clientVertex.label(), "Value",
                clientVertex.value("Value"), 
                "Property1-1", clientVertex.value("Property1-1"), 
                "Property1-2", clientVertex.value("Property1-2"));
        break;

    case "Label 2":
        newVertex = graph.addVertex(T.label, clientVertex.label(), "Value",
                clientVertex.value("Value"), "Property2-1",
                clientVertex.value("Property2-1"),
                "Property2-2", clientVertex.value("Property2-2"));
        break;

    default:
        newVertex = graph.addVertex(T.label, clientVertex.label(), "Value",
                clientVertex.value("Value"));
        break;
    }
    return newVertex;
}

スキーマ定義: (いくつかのインデックスを表示)
注:
"EdgeLabel" = Constants.EdgeLabels.Uses
"EdgeProperty1" = Constants.EdgePropertyKeys.EndpointId
"EdgeProperty2" = Constants.EdgePropertyKeys.Timestamp

public void createSchema() {
    // Create Schema
    TitanManagement mgmt = dbgraph.openManagement();
    mgmt.set("cache.db-cache",true);

    // Vertex Properties
    PropertyKey value = mgmt.getPropertyKey(Constants.VertexPropertyKeys.Value);
    if (value == null) {
        value = mgmt.makePropertyKey(Constants.VertexPropertyKeys.Value).dataType(String.class).make();
        mgmt.buildIndex(Constants.GraphIndexes.ByValue, Vertex.class).addKey(value).buildCompositeIndex(); // INDEX
    }

    PropertyKey shapeSet = mgmt.getPropertyKey(Constants.VertexPropertyKeys.ShapeSet);
    if (shapeSet == null) {
        shapeSet = mgmt.makePropertyKey(Constants.VertexPropertyKeys.ShapeSet).dataType(String.class).cardinality(Cardinality.SET).make();
        mgmt.buildIndex(Constants.GraphIndexes.ByShape, Vertex.class).addKey(shapeSet).buildCompositeIndex();
    }
    ...

    // Edge Labels and Properties
    EdgeLabel uses = mgmt.getEdgeLabel(Constants.EdgeLabels.Uses);
    if (uses == null) {
        uses = mgmt.makeEdgeLabel(Constants.EdgeLabels.Uses).multiplicity(Multiplicity.MULTI).make();

        PropertyKey timestampE = mgmt.getPropertyKey(Constants.EdgePropertyKeys.Timestamp);
        if (timestampE == null) {
            timestampE = mgmt.makePropertyKey(Constants.EdgePropertyKeys.Timestamp).dataType(Long.class).make();
        }

        PropertyKey endpointIDE = mgmt.getPropertyKey(Constants.EdgePropertyKeys.EndpointId);
        if (endpointIDE == null) {
            endpointIDE = mgmt.makePropertyKey(Constants.EdgePropertyKeys.EndpointId).dataType(String.class).make();
        }

        // Indexes
        mgmt.buildEdgeIndex(uses, Constants.EdgeIndexes.ByEndpointIDAndTimestamp, Direction.BOTH, endpointIDE,
                timestampE);
    }

    mgmt.commit();
}
4

1 に答える 1