Ответ 1
Я один из основных разработчиков ArangoDB
и попытался оптимизировать ваш запрос. Поскольку у меня нет вашего dataset
, я могу говорить только о своем тесте dataset
и был бы рад услышать, можете ли вы подтвердить мои результаты.
Сначала, если все работает на ArangoDB
2.7, но в этом конкретном случае я не ожидаю значительного разницы в производительности до 2.6.
В моем dataset
я мог выполнить ваш запрос, как в ~ 7 сек.
Первое исправление:
В заявлении ваших друзей вы используете includeData: true
и возвращаете только _id
. С includeData: false
GRAPH_NEIGHBORS
прямо возвращается _id
, и мы также можем избавиться от подзапроса здесь
LET friends = GRAPH_NEIGHBORS('graph',
@user,
{"direction": "any",
"edgeExamples": {
name: "FRIENDS_WITH"
}})
Это снизилось до ~ 1,1 секунды на моей машине. Поэтому я ожидаю, что это будет близко к производительности Neo4J.
Почему это имеет большое значение?
Внутри мы сначала находим значение _id
без фактической загрузки документов JSON. В вашем запросе вам не нужны какие-либо данные, поэтому мы можем спокойно продолжать, не открывая его.
Но теперь для реального улучшения
Ваш запрос идет "логичным" способом и сначала получает пользователей соседей, чем находит своих соседей, подсчитывает, как часто найден foaf
и сортирует его.
Это должно создать полную foaf-сеть в памяти и отсортировать ее в целом.
Вы также можете сделать это по-другому:
1. Найдите всех пользователей friends
(только _ids
)
2. Найдите все foaf
(полный документ)
3. Для каждого foaf
найдите все foaf_friends
(только _ids
)
4. Найдите пересечение friends
и foaf_friends
и COUNT их
Этот запрос хотел бы:
LET fids = GRAPH_NEIGHBORS("graph",
@user,
{
"direction":"any",
"edgeExamples": {
"name": "FRIENDS_WITH"
}
}
)
FOR foaf IN GRAPH_NEIGHBORS("graph",
@user,
{
"minDepth": 2,
"maxDepth": 2,
"direction": "any",
"includeData": true,
"edgeExamples": {
"name": "FRIENDS_WITH"
}
}
)
LET commonIds = GRAPH_NEIGHBORS("graph",
foaf._id, {
"direction": "any",
"edgeExamples": {
"name": "FRIENDS_WITH"
}
}
)
LET common_friend_count = LENGTH(INTERSECTION(fids, commonIds))
SORT common_friend_count DESC
RETURN {user: foaf, common_friend_count: common_friend_count}
Какой на моем тестовом графике был выполнен в ~ 0.024 сек
Таким образом, это дало мне более быстрое время выполнения на 250 раз, и я ожидал бы, что это будет быстрее, чем ваш текущий запрос в Neo4j, но поскольку у меня нет вашего dataset
, я не могу его проверить, было бы хорошо, если бы вы мог бы это сделать и сказать мне.
Последняя вещь
С edgeExamples: {name : "FRIENDS_WITH" } it is the same as with
includeData`, в этом случае мы должны найти реальное ребро и изучить его. Этого можно избежать, если вы храните свои ребра в разных коллекциях на основе их имени. Затем удалите также примеры edgeExamples. Это еще больше повысит производительность (особенно если есть много краев).
Future
Оставайтесь с нами в связи с нашей следующей версией, мы сейчас добавили еще несколько функций для AQL, которые значительно упростят ваш запрос и должны повысить производительность.