graph-databases arangodb aql

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.