2013-05-07 2 views
1

Этот вопрос аналогичен этим двум: 16283441, 15456345.отношения с соседними соседями cypher query

ОБНОВЛЕНИЕ: здесь database dump.

в БД 190K узлов и 727K отношений (и 128 Мб дискового использования базы данных), я хотел бы выполнить следующую команду query:

START start_node=node(<id>) 
MATCH (start_node)-[r:COOCCURS_WITH]-(partner), 
     (partner)-[s:COOCCURS_WITH]-(another_partner)-[:COOCCURS_WITH]-(start_node) 
RETURN COUNT(DISTINCT s) as num_partner_partner_links; 

В этом DB 90% узлов имеют отношения 0 , а оставшиеся 10% имеют от 1 до 670, поэтому самая большая сеть, к которой может вернуться этот запрос, не может иметь более 220 Кбит/с (670 * 670)/2).

На узлах с партнером_partner_links менее 10 тыс. Запрос занимает 2-4 секунды, когда он прошивается. Для более узких узлов (ссылки 20-45K) требуется около 40-50 секунд (не знаете, сколько потребуется для самых подключенных).

Указание направления отношений помогает немного, но не так много (но тогда запрос не возвращает то, что мне нужно для его возврата).

Профилирование запроса на одном из самых больших узлов говорит:

==> ColumnFilter(symKeys=[" INTERNAL_AGGREGATE48d9beec-0006-4dae-937b-9875f0370ea6"], returnItemNames=["num_partner_links"], _rows=1, _db_hits=0) 
==> EagerAggregation(keys=[], aggregates=["( INTERNAL_AGGREGATE48d9beec-0006-4dae-937b-9875f0370ea6,Distinct)"], _rows=1, _db_hits=0) 
==> PatternMatch(g="(partner)-['r']-(start_node)", _rows=97746, _db_hits=34370048) 
==>  TraversalMatcher(trail="(start_node)-[ UNNAMED3:COOCCURS_WITH WHERE true AND true]-(another_partner)-[s:COOCCURS_WITH WHERE true AND true]-(partner)", _rows=116341, _db_hits=117176) 
==>  ParameterPipe(_rows=1, _db_hits=0) 
neo4j-sh (0)$ 

Я не вижу, почему бы это так медленно, большая часть материала должна быть в памяти в любом случае. Возможно ли, чтобы это было менее чем за 100 мс, или neo4j не справляется с этим? Я мог бы поставить весь дб где-то, если это поможет ..

Самая большая загадка в том, что тот же запрос работает медленнее, когда переписаны для использования с различными узловыми символов :)

START n=node(36) 
MATCH (n)-[r:COOCCURS_WITH]-(m), 
     (m)-[s:COOCCURS_WITH]-(p)-[:COOCCURS_WITH]-(n) 
RETURN COUNT(DISTINCT s) AS num_partner_partner_links; 

START start_node=node(36) 
MATCH (start_node)-[r:COOCCURS_WITH]-(partner), 
     (partner)-[s:COOCCURS_WITH]-(another_partner)-[:COOCCURS_WITH]-(start_node) 
RETURN COUNT(DISTINCT s) AS num_partner_partner_links; 

Бывший всегда бежит в +4,2 секунды, а последний менее 3,8, независимо от того, сколько раз я запускаю один и другой (чередующийся) !?

SW/HW деталь: (расширенный) Neo4j v1.9.RC2, JDK 1.7.0.10, Макбук про с SSD диском, 8GBRAM, 2 Core i7, со следующей конфигурацией: Neo4j

neostore.nodestore.db.mapped_memory=550M 
neostore.relationshipstore.db.mapped_memory=540M 
neostore.propertystore.db.mapped_memory=690M 
neostore.propertystore.db.strings.mapped_memory=430M 
neostore.propertystore.db.arrays.mapped_memory=230M 
neostore.propertystore.db.index.keys.mapped_memory=150M 
neostore.propertystore.db.index.mapped_memory=140M 

wrapper.java.initmemory=4092 
wrapper.java.maxmemory=4092 

ответ

0

Измените ваш запрос ниже. На моем ноутбуке, с существенно более низкими характеристиками, чем у вас, время исполнения половины.

START start_node=node(36) 
MATCH (start_node)-[r:COOCCURS_WITH]-(partner) 
WITH start_node, partner 
MATCH (partner)-[s:COOCCURS_WITH]-(another_partner)-[:COOCCURS_WITH]-(start_node) 
RETURN COUNT(DISTINCT s) AS num_partner_partner_links; 

Кроме того, использование ваших настроек не влияет на производительность значительно по сравнению с настройками по умолчанию. Я боюсь, что вы не сможете получить нужную производительность, но этот запрос является шагом в правильном направлении.

Обычно API обхода будет быстрее, чем Cypher, потому что вы явно контролируете обход. Я подражал запрос следующим образом:

public class NeoTraversal { 

public static void main(final String[] args) { 
    final GraphDatabaseService db = new GraphDatabaseFactory() 
      .newEmbeddedDatabaseBuilder("/neo4j") 
      .loadPropertiesFromURL(NeoTraversal.class.getClassLoader().getResource("neo4j.properties")) 
      .newGraphDatabase(); 
    final Set<Long> uniquePartnerRels = new HashSet<Long>(); 
    long startTime = System.currentTimeMillis(); 
    final Node start = db.getNodeById(36); 
    for (final Path path : Traversal.description() 
      .breadthFirst() 
      .relationships(Rel.COOCCURS_WITH, Direction.BOTH) 
      .uniqueness(Uniqueness.NODE_GLOBAL) 
      .evaluator(Evaluators.atDepth(1)) 
      .traverse(start)) { 
     Node partner = start.equals(path.startNode()) ? path.endNode() : path.startNode(); 
     for (final Path partnerPath : Traversal.description() 
       .depthFirst() 
       .relationships(Rel.COOCCURS_WITH, Direction.BOTH) 
       .uniqueness(Uniqueness.RELATIONSHIP_PATH) 
       .evaluator(Evaluators.atDepth(2)) 
       .evaluator(Evaluators.includeWhereEndNodeIs(start)) 
       .traverse(partner)) { 
      uniquePartnerRels.add(partnerPath.relationships().iterator().next().getId()); 
     } 
    } 
    System.out.println("Execution time: " + (System.currentTimeMillis() - startTime)); 
    System.out.println(uniquePartnerRels.size()); 
} 

static enum Rel implements RelationshipType { 
    COOCCURS_WITH 
} 

} 

Это явно превосходит Cypher запрос, таким образом, это может быть хорошей альтернативой для вас. Оптимизация, вероятно, все еще возможна.

+0

Вы правы на оба, ваш запросе шифровать несколько быстрее, и запрос обхода является по крайней мере, в 2 раза быстрее! Но он все еще не там, где мне нужно:/на результатах 10K он занимает 1сек, для самого большого узла - 20 сек. Ps. в вашем обходном запросе было 2 ошибки, надеюсь, что мне хорошо отредактировать ваш ответ. – milan

+0

Вы можете получить немного скорости, добавив идентификаторы отношений в набор. Я снова редактировал код. Вы снова выиграете, но, конечно, не будете делать чудес. – tstorms

+0

Самые большие узкие места в том, что вам нужно пройти в обоих направлениях. Невозможно ли смоделировать ваши данные только в одном направлении? – tstorms

0

Кажется, что ничего, кроме глубины/ширины первого обхода, neo4j не то, что «пылает быстро». Я решил проблему, предварительно вычислив все сети и сохранив их в MongoDB.Документ, описывающий узел сети выглядит следующим образом:

{ 
    node_id : long, 
    partners : long[], 
    partner_partner_links : long[] 
} 

Партнеры и partner_partner_links являются идентификаторами документов, описывающих egdes. Получение всей сети занимает 2 запросов: один для данного документа, а другое для краевых свойств (который также имеет свойство узла):

db.edge.find({"_id" : {"$in" : network.partner_partner_links}}); 
Смежные вопросы