2017-02-08 5 views
3


Я новичок в Neo4j. На данный момент я оцениваю использование Neo4j для одного из наших вариантов использования. У меня возникают проблемы, когда я пытаюсь объединить с большим количеством узлов.Neo4j: медленная агрегация с большим количеством узлов

Мы используем Neo4j для хранения посетителей, которые подали голоса, относящиеся к разным категориям. В голосовании есть место и реферер, который я смоделировал как отдельные узлы, чтобы «повторно использовать» их.
Это примерно то, что моя схема выглядит (Node Голосуйте имеет дополнительные отношения, которые я здесь опуская):

(Visitor {id})-[VOTED]->(Vote)-[RELATES_TO]->(Category {name}) 

с индексом на Vistor.id и Category.name

Наш набор данных довольно велик , поэтому я начал тестировать свою схему с 4 миллионами голосов и 3 миллионами посетителей. Голоса относятся к 18 различным категориям.
Я хочу иметь возможность делать скопления. Например, мне нужно получить количество отдельных посетителей, которые проголосовали за категории «А» и «CATEGORY B».

MATCH (c:Category)<-[:PARENT*0..3]-(child:Category)<-[:RELATES_TO]-(v:Vote)<-[:VOTED]-(visitor:Visitor) 
WHERE c.name = 'Category A' 
WITH visitor 
MATCH (c:Category)<-[:RELATES_TO]-(v:Vote)<-[:VOTED]-(visitor) 
WHERE c.name = 'Category B' 
RETURN count(distinct(visitor.id)) as Cat_A_and_B_lovers 

Это занимает почти 30 секунд

Я хотел бы также, чтобы иметь возможность получить все категории и количество различных голосов:

MATCH (n:Category)<-[:RELATES_TO]-(:Vote)<-[:VOTED]-(v:Visitor) 
RETURN n.name as category, count(DISTINCT v) as count; 

Это занимает 13 секунд.

Возможно ли улучшить эти тайминги, или Neo4j просто не подходит для такого анализа?

Мы также анализируем данные на уровне каждого посетителя, но также хотели бы иметь возможность делать эти агрегации.

Мои настройки:
Linux, 4 ядра 14GB
Noe4j сообщество версия
neo4j.conf:

dbms.memory.heap.initial_size = 2G 
dbms.memory.heap.max_size = 10G 
dbms.memory.pagecache.size = 10g 

- ОБНОВЛЕНИЕ 15/02

Следующие предложения Майкла я был способный улучшить время выполнения обоих запросов. Мой первый вопрос: выход

PROFILE MATCH (n:Category)<-[:RELATES_TO]-()<-[:VOTED]-(v:Visitor) 
WITH n, count(DISTINCT v) as count 
RETURN n.name as category, count 

ПРОФИЛЬ:

9964 мс

Компилятор CYPHER 3,1

Планировщик COST

Продолжительность INTERPRETED

+-------------------+----------------+---------+---------+--------------------------------------+------------------------------------+ 
| Operator   | Estimated Rows | Rows | DB Hits | Variables       | Other        | 
+-------------------+----------------+---------+---------+--------------------------------------+------------------------------------+ 
| +ProduceResults |   1545 |  18 |  0 | category, count      | category, count     | 
| |     +----------------+---------+---------+--------------------------------------+------------------------------------+ 
| +Projection  |   1545 |  18 |  18 | category -- count, n     | {category : n.name, count : count} | 
| |     +----------------+---------+---------+--------------------------------------+------------------------------------+ 
| +EagerAggregation |   1545 |  18 |  0 | count -- n       | n         | 
| |     +----------------+---------+---------+--------------------------------------+------------------------------------+ 
| +Filter   |  2386269 | 4114784 | 4114784 | anon[19], anon[35], anon[37], n, v | v:Visitor       | 
| |     +----------------+---------+---------+--------------------------------------+------------------------------------+ 
| +Expand(All)  |  2386269 | 4114784 | 8229568 | anon[37], v -- anon[19], anon[35], n |()<-[:VOTED]-(v)     | 
| |     +----------------+---------+---------+--------------------------------------+------------------------------------+ 
| +Expand(All)  |  4113784 | 4114784 | 4114807 | anon[19], anon[35] -- n    | (n)<-[:RELATES_TO]-()    | 
| |     +----------------+---------+---------+--------------------------------------+------------------------------------+ 
| +NodeByLabelScan |    23 |  23 |  24 | n         | :Category       | 
+-------------------+----------------+---------+---------+--------------------------------------+------------------------------------+ 

Это займет почти 10 секунд. Мне нужно было бы получить его ниже 1 секунды. Возможно ли это вообще (используя neo4j)?

+0

Это может быть лучше подходит для обзора кода. Stack Overflow здесь, чтобы помочь с реальной проблемой, означающей «исправление чего-то, что не работает», в отличие от «улучшения чего-то, что работает». –

+0

Как насчет индекса? –

+0

У меня есть индекс на Vistor.id и Category.name. – Johanna

ответ

0

Не настраивайте больше памяти, чем у вас.

Set страница кэша 4G и мин/макс кучи до 8

для запроса было бы хорошо, чтобы посмотреть на план выполнения запроса с EXPLAIN и PROFILE.

Я рекомендую что-то вроде этого:

MATCH (ca:Category)<-[:PARENT*0..3]-(child)<-[:RELATES_TO]-()<-[:VOTED]-(visitor) 
WHERE ca.name = 'Category A' 
WITH distinct visitor 
MATCH (cb:Category)<-[:RELATES_TO]-()<-[:VOTED]-(visitor) 
USING INDEX cb:Category(name) 
WHERE cb.name = 'Category B' 
RETURN count(distinct(visitor)) as Cat_A_and_B_lovers 

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

Сколько у вас пользователей? Вы можете также перевернуть два вокруг, то есть сначала сделать «B», затем «A».

MATCH (cb:Category)<-[:RELATES_TO]-()<-[:VOTED]-(visitor) 
WHERE cb.name = 'Category B' 
WITH distinct visitor 
MATCH (ca:Category)<-[:PARENT*0..3]-(child)<-[:RELATES_TO]-()<-[:VOTED]-(visitor) 
USING INDEX ca:Category(name) 
WHERE ca.name = 'Category A' 
RETURN count(distinct(visitor)) as Cat_A_and_B_lovers 

Кроме того, для подсчета его только дорого и не выгодно, чтобы рассчитывать свойства (visitor.id), когда сами узлы представляют собой ту же концепцию.

+0

Спасибо, Майкл. Следуя вашим предложениям, я могу значительно улучшить время выполнения своих запросов. Тем не менее, я нигде не близок к моей цели, которая получает время выполнения менее одной секунды для каждого из этих запросов. Является ли эта цель осуществимой с моим объемом данных? – Johanna

 Смежные вопросы

  • Нет связанных вопросов^_^