Узлы высокой степени в neo4j
Я пытаюсь понять эффективные шаблоны использования с neo4j, особенно в отношении узлов высокой степени. Чтобы дать представление о том, о чем я говорю, у меня есть User
узлы, которые имеют атрибуты, которые я смоделировал как узлы. Так что в моей таблице есть отношения, такие как
(:User)-[:HAS_ATTRIB]->(:AgeCategory)
и так далее и тому подобное. Проблема в том, что некоторые из них AgeCategory
узлы очень высокой степени, порядка 100 КБ, и такие запросы, как
MATCH (u:User)-->(:AgeCategory)<--(v:User), (u)-->(:FavoriteLanguage)<--(v)
WHERE u.uid = "AAA111" AND v.uid <> u.uid
RETURN v.uid
(соответствует всем пользователям, которые имеют ту же возрастную категорию и любимый язык, что и AAA111
) очень, очень медленно, так как вы должны бежать FavoriteLanguage
связанный список один раз для каждого элемента в AgeCategory
связанный список (или, по крайней мере, я так понимаю).
Я думаю, это довольно ясно из того факта, что этот запрос занимает минуты, чтобы решить, что я делаю что-то не так, но мне любопытно, какова правильная процедура для работы с такими запросами. Должен ли я вывести соответствующих пользователей из каждого запроса по отдельности и сравнить их с хэшем в памяти? Есть ли способ поставить индекс на отношения на узле? Это даже хорошая идея для схемы для начала?
1 ответ
Моя интуиция заключается в том, что было бы более эффективно сначала получить две конечные точки (AgeCategory и FavoriteLanguage) для данного узла u, а затем запросить средний узел v для пути с этими двумя фиксированными конечными точками.
Чтобы доказать это, я создал тестовый граф со следующими компонентами:
- Узел u: Пользователь с u.uid = 'AAA111'
- Узел c:AgeCategory
- Узел l:FavoriteLanguage
- Отношения между u и c, u-[:HAS_AGE]->c
- Отношения между u и l, u - [: LIKE_LANGUAGE] -> l
- 100 000 узлов v, каждый из которых имеет одинаковые c:AgeCategory и l:FavoriteLanguage с ndoe u, то есть каждый v соединяется с l и c, v-[:HAS_AGE]->c, v-[:LIKE_LANGUAGE]-> L
Я выполнил следующий запрос 10 раз и получил среднее время выполнения 10500 миллис.
Match l:FavoriteLanguage<-[:LIKE_LANGUAGE]-u:User-[:HAS_AGE]->c:AgeCategory
Where u.uid = 'AAA111'
With l,c
Match l<-[:LIKE_LANGUAGE]-v:User-[:HAS_AGE]->c
Where v.uid <> 'AAA111'
Return v.uid
При 10 000 v узлах этот запрос занимает около 2000 миллис, а ваш запрос - около 27000 миллис.
С узлом 100000 v этот запрос занимает около 10500 миллисекунд, кажется, он будет длиться вечно с вашим исходным запросом.
Таким образом, вы можете попробовать этот запрос и посмотреть, сможет ли он улучшить производительность вашего графика.