2016-09-02 12 views
1

Я работаю с titan 1.0, используя локальную реализацию AWS dynamoDB в качестве хранилища для хранения на машине 16 ГБ. Мой случай использования включает в себя создание графов, периодически содержащих вершины & ребер порядка 120K. Каждый раз, когда я создаю новый график в памяти, я проверяю график, хранящийся в БД, и (i) добавляю вершины/ребра, которые не существуют, или (ii) обновляет свойства, если они уже существуют (существование определяется «Метка», и атрибут «Значение»). Обратите внимание, что свойство «Значение» индексируется. Транзакции совершаются партиями по 500 вершин.Обработка диаграмм становится все медленнее на titan + dynamoDB (local), когда добавляется больше вершин/ребер

Проблема: Я считаю, что этот процесс становится медленнее каждый раз, когда я обрабатывать новый граф (первый граф закончил в 45 минут с пустой БД изначально, второй занял 2,5 часа, 3 в 3,5 часа, 4-й по 6 часов, пятые через 10 часов и т. д.). Фактически, при обработке данного графика он довольно быстр во время запуска, но постепенно становится медленнее (начальные партии занимают 2-4 секунды, а затем он увеличивается до 100 секунд для одного и того же размера партии 500 узлов, иногда я вижу занимает 1000-2000 секунд для партии). Это только время обработки (см. Подход ниже); commit берет между 8-10 сек всегда. Я настроил размер кучи jvm на 10G, и я заметил, что когда приложение работает, оно в конечном итоге использует все это.

Вопрос: Можно ли ожидать этого? Мне кажется, что-то здесь не так (или в моем config/подходе?). Любая помощь или предложения были бы весьма признательны.

подход:

  • Начиная с корневого узла графа в памяти, я получить все дочерние узлы и поддерживать очередь
  • Для каждого дочернего узла, я проверяю, если это существует в БД, иначе создать новый узел, и обновить некоторые свойства

    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(); 
} 
+0

Вы указали какие-либо индексы? Если да, можете ли вы включить эти определения в свой вопрос? http://s3.thinkaurelius.com/docs/titan/1.0.0/indexes.html –

+0

отредактировал вопрос, чтобы включить определения индексов ... – tritone

+0

Как вы настроили кеш Гремлина? Используете ли вы параметризованные запросы? По умолчанию Gremlin сохраняет каждый запрос в кеше до тех пор, пока у вас не закончится память. Вы можете [изменить это поведение] (http://tinkerpop.apache.org/docs/current/reference/#_cache_management) или параметризовать свои запросы. –

ответ

0

Ожидаемое поведение. Сегодня DynamoDB Local - это инструмент тестирования, построенный на SQLite. Если вам необходимо поддерживать высокий TPS для больших и периодических нагрузок данных, я рекомендую использовать службу DynamoDB.