2017-01-19 1 views
2

J'ai travaillé sur un système de gestion de configuration utilisant arangodb qui collecte des données de configuration pour certains logiciels courants et les transmet à un programme qui va générer la relation entre ces logiciels basés sur -défini les règles, puis enregistrez les relations dans arangodb. Après les relations établies, je fournis des API pour interroger les données. Une question importante est de générer la topologie de ces logiciels. J'utilise traversal graphique pour générer la topologie avec AQL suivante:Les performances baissent considérablement lorsque les niveaux sont plus longs dans le graphique travelsal

for n in nginx for v,e,p in 0..4 outbound n forward, dispatch, route,INBOUND deployto, referto,monitoron filter @domain in p.edges[0].server_name return {id: v._id, type: v.ci_type} 

qui peut générer la topologie suivante: software relation topology

Ce qui a l'air bien. Cependant, il faut environ 10 secondes pour terminer la requête, ce qui n'est pas acceptable car le volume n'est pas très important. J'ai vérifié toutes les collections et la plus grande collection, la collection "avant" de bord a seulement environ 28000 documents. J'ai donc fait quelques tests: J'ai changé la profondeur de 0..4 à 0..2 et cela prend seulement 0.3 seconde pour terminer la requête J'ai changé la profondeur de 0..4 à 0..3, cela prend environ 3 secondes pour 0..4, il faut environ 10 secondes Puisqu'il y a une propriété server_name sur le front "forward", donc j'ajoute un hash index (server_name [*]) mais il semble que arangodb n'utilise pas l'index du expliquer le plan d'exécution Des conseils pour optimiser la requête? et pourquoi l'index ne peut pas être utilisé dans ce cas?

J'espère que quelqu'un pourra m'aider avec ça. Merci à l'avance,

+0

J'ai vu des requêtes ralentir comme ça aussi, mais la cause de la lenteur peut parfois être juste le volume de données retournées. Avez-vous essayé de mesurer la taille de la réponse lors du retour des données pour 0..2 par rapport à 0..4? Vous vous demandez s'il y a des surprises là-dedans autour de la taille de la réponse. –

+0

En fait, les données de retour sont dans un petit ensemble. C'est un vecteur d'environ 400 éléments qui a hashmap à deux champs pour 0..4. – hughjfchen

Répondre

2

Tout d'abord, j'ai essayé votre requête et je pouvais voir que, pour une raison quelconque le:

filter @domain in p.edges[0].server_name 

n'est pas optimisé correctement. Cela semble être un problème interne avec la règle d'optimisation n'étant pas assez bon, je vais prendre un examen détaillé dans ce domaine et essayer de s'assurer que cela fonctionne comme prévu. Pour cette raison, il ne sera pas encore en mesure d'utiliser un index différent pour ce cas, et ne fera pas de court-circuit pour interrompre la recherche au niveau 1 correctement. Je suis désolé pour le dérangement, car la façon dont vous l'avez fait devrait être la bonne.

Pour avoir une solution rapide pour l'instant, vous pouvez diviser la première partie de la requête dans une étape séparée:

Ceci est la version rapide de ma requête modifiée (qui ne comprend pas le nginx, voir la version plus lente)

FOR n IN nginx 
    FOR forwarded, e IN 1 OUTBOUND forward 
    FILTER @domain IN e.server_name 
    /* At this point we only have the relevant first depth vertices*/ 
    FOR v IN 0..3 OUTBOUND forward, dispatch, route, INBOUND deployto, referto, monitoron 
     RETURN {id: v._id, type: v.ci_type} 

Ceci est une version légèrement plus lent de ma requête modifiée (enregistrement de votre format de sortie, et je pense que ce sera plus rapide que celui sur lequel vous travaillez avec)

FOR tmp IN(
    FOR n IN nginx 
    FOR forwarded, e IN 1 OUTBOUND forward 
     FILTER @domain IN e.server_name 
     /* At this point we only have the relevant first depth vertices*/ 
     RETURN APPEND([{id: n._id, type: n.ci_type}],(
     FOR v IN 0..3 OUTBOUND forward, dispatch, route, INBOUND deployto, referto, monitoron 
     RETURN {id: v._id, type: v.ci_type} 
    ) 
)[**] 
RETURN tmp 

Dans je peux donner un général conseiller:

  1. (Cela fonctionne après nous avons fixé l'optimiseur) Utilisation de l'index: ArangoDB utilise des statistiques/hypothèses de la sélectivité de l'indice (comment il est bon de trouver les données) pour décider quel indice est le meilleur. Dans votre cas, il peut supposer que l'index de bord est meilleur que votre index de hachage. Vous pouvez essayer de créer un hash_index combiné sur ["_from", "server_name [*]"] qui est plus susceptible d'avoir une meilleure estimation que EdgeIndex et pourrait être utilisé.
  2. Dans l'exemple que vous avez donné, je peux voir qu'il y a une grande partie droite commençant au niveau du noeud apppkg.Dans la requête cette partie droite peut être atteinte de deux manières: a) nginx -> tomcat < - apppkg b) nginx -> vernis -> lvs -> tomcat < - apppkg Cela signifie que la requête pourrait passer par le sous-arbre de départ à apppkg plusieurs fois (une fois pour chaque chemin qui y mène). Avec la profondeur de requête de 4 et seulement cette topologie ne se produit pas, mais s'il y a des chemins plus courts cela peut aussi être un problème. Si je ne me trompe pas que vous n'êtes intéressé que par les sommets distincts dans le graphique et le chemin n'est pas important non? Si tel est le cas, vous pouvez ajouter OPTIONS à la requête pour vous assurer qu'aucun sommet (et sous-arbre dépendant) n'est analysé deux fois. La requête modifiée ressemblerait à ceci:

    pour n dans nginx pour v, e, p dans 0..4 sortant n avant, l'expédition, la route, deployto ENTRANT, referto, monitoron OPTIONS {BFS: true, uniqueVertices : "global"} filtre @domaine dans p.edges [0] .server_name return {id: v._id, tapez: v.ci_type}

le changement que je fait est que j'ajouter des options à la traversée: bfs: true => Signifie que nous faisons une recherche en largeur au lieu d'une recherche en profondeur d'abord, nous avons seulement besoin de ceci pour rendre le résultat déterministe et nous assurer que tous les sommets avec un chemin de d epth 4 sera atteint correctement uniqueVertices: "global" => Signifie que chaque fois qu'un vertex est trouvé dans une traversée (donc dans chaque cas pour chaque nginx séparément) il est marqué et ne sera pas regardé à nouveau.

Si vous avez également besoin de la liste de toutes les arêtes distinctes, vous devez utiliser uniqueEdges: "global" au lieu de uniqueVertices: "global" ce qui rendra cette vérification d'unicité au niveau des arêtes.

+0

, Merci pour votre réponse si informative et des conseils utiles. La suggestion # 1 est exactement ce que j'essaie de tester ensuite et je suis impatient de votre mise à jour pour l'optimiseur de requête. – hughjfchen

+0

Salut, @ mchacki, j'ai appliqué le # 2 et le temps de chute à 2 secondes. C'est génial mais j'aimerais que ça se termine dans 1 seconde. Alors, je peux demander quels sont les progrès sur # 1? Puis-je utiliser l'index de certaines propriétés d'un bord maintenant? – hughjfchen