graph databases - ¿Cuál es la consulta más rápida de amigos de ArangoDB(con conteo)?
graph-databases aql (1)
Estoy tratando de usar ArangoDB para obtener una lista de amigos de amigos. No solo una lista básica de amigos de amigos, también quiero saber cuántos amigos tienen en común el usuario y el amigo de un amigo y ordenar el resultado. Después de varios intentos de (re) escribir la consulta AQL con el mejor rendimiento, esto es lo que terminé con:
LET friends = (
FOR f IN GRAPH_NEIGHBORS(''graph'', @user, {"direction": "any", "includeData": true, "edgeExamples": { name: "FRIENDS_WITH"}})
RETURN f._id
)
LET foafs = (FOR friend IN friends
FOR foaf in GRAPH_NEIGHBORS(''graph'', friend, {"direction": "any", "includeData": true, "edgeExamples": { name: "FRIENDS_WITH"}})
FILTER foaf._id != @user AND foaf._id NOT IN friends
COLLECT foaf_result = foaf WITH COUNT INTO common_friend_count
RETURN {
user: foaf_result,
common_friend_count: common_friend_count
}
)
FOR foaf IN foafs
SORT foaf.common_friend_count DESC
RETURN foaf
Desafortunadamente, el rendimiento no es tan bueno como me hubiera gustado. En comparación con las versiones Neo4j de la misma consulta (y datos), AQL parece un poco más lento (5-10x).
Lo que me gustaría saber es ... ¿Cómo puedo mejorar nuestra consulta para mejorar el rendimiento?
Soy uno de los desarrolladores principales de ArangoDB
y traté de optimizar su consulta. Como no tengo su dataset
, solo puedo hablar sobre mi dataset
prueba y me dataset
saber si puede validar mis resultados.
Primero si todo lo que estoy ejecutando en ArangoDB
2.7, pero en este caso particular no espero una diferencia de rendimiento mayor a 2.6.
En mi dataset
podría ejecutar su consulta como está en ~ 7 seg. Primer arreglo: en la declaración de tus amigos usas includeData: true
y solo devuelve el _id
. Con includeData: false
GRAPH_NEIGHBORS
devuelve directamente el _id
y también podemos deshacernos de la subconsulta aquí
LET friends = GRAPH_NEIGHBORS(''graph'',
@user,
{"direction": "any",
"edgeExamples": {
name: "FRIENDS_WITH"
}})
Esto lo redujo a ~ 1.1 seg en mi máquina. Así que espero que esto se acerque al rendimiento de Neo4J.
¿Por qué esto tiene un alto impacto? Internamente, primero encontramos el valor _id
sin cargar realmente los documentos JSON. En su consulta, no necesita ninguno de estos datos, por lo que podemos continuar sin abrirlos.
Pero ahora para la mejora real.
Su consulta sigue el camino "lógico" y primero obtiene vecinos de los usuarios, luego encuentra a sus vecinos, cuenta la frecuencia con la que se encuentra un foaf
y lo clasifica. Esto tiene que construir la red completa de foaf en memoria y clasificarla como un todo.
También puede hacerlo de una manera diferente: 1. Encuentre todos los friends
del usuario (solo _ids
) 2. Encuentre todos los foaf
(documento completo) 3. Para cada foaf
encuentre todos los foaf_friends
(solo _ids
) 4. Encuentre la intersección de friends
y foaf_friends
y CUENTA ellos
Esta consulta le gustaría esto:
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}
Que en mi gráfico de prueba fue ejecutado en ~ 0.024 seg.
Así que esto me dio un factor de tiempo de ejecución 250 más rápido y esperaría que fuera más rápido que su consulta actual en Neo4j, pero como no tengo su dataset
no puedo verificarlo, sería bueno si pudiera hacerlo y decirle yo.
Una última cosa
Con los edgeExamples: {name : "FRIENDS_WITH" }
es igual que con includeData
, en este caso tenemos que encontrar el borde real y examinarlo. Esto podría evitarse si almacena sus bordes en colecciones separadas según su nombre. Y luego quitar los ejemplos de borde también. Esto aumentará aún más el rendimiento (especialmente si hay muchos bordes).
Futuro
Manténgase atento a nuestra próxima versión, ahora mismo estamos agregando algunas funciones más a AQL, lo que hará que su caso sea mucho más fácil de consultar y debería dar otro impulso de rendimiento.