2016-04-03 12 views
1

Ich bewerte ArangoDB und ich sehe, dass GRAPH_EDGES und GRAPH_VERTICES Befehle sehr langsam sind, auf kleine Sammlungen (300 Vertices).ArangoDB: GRAPH_EDGES Befehl sehr langsam (mehr als 20 Sek.) Auf kleine Sammlungen

I 3 Sammlungen haben:

TactiveService (300 Knoten) -> TusesCommand (300 Edges) -> Tcommand (1 Vertex)

GRAPH_EDGES verwenden, nehmen Sie diese Abfrage 24 sec

FOR service IN TactiveService 
    LET usesCommand = (
     return FIRST(GRAPH_EDGES("topvision", {}, { edgeExamples : [{_from: service._id}], edgeCollectionRestriction : "TusesCommand", includeData:true, maxDepth : 1 })) 
    ) 
    LET command = DOCUMENT(usesCommand[0]._to) 
RETURN { service : service, usesCommand: usesCommand[0], command:command} 

Aus dem gleichen Ergebnis, diese Abfrage dauert 0,020 sec

FOR service IN TactiveService 
    LET usesCommand = (
     FOR usesCommand IN TusesCommand 
     FILTER usesCommand._from == service._id 
     RETURN usesCommand 
    ) 
    LET command = DOCUMENT(usesCommand[0]._to) 
RETURN { service : service, usesCommand: usesCommand[0], command:command} 

GRAPH_EDGES ist unbrauchbar für mich FOR-Anweisung (gleiches Problem mit GRAPH_VERTICES) in.

Ideen über den Grund dieser Langsamkeit sind willkommen.

Antwort

3

Uns ist bewusst, dass GRAPH_EDGES nicht gut geeignet ist, um so in einer Abfrage verwendet werden.

Wir haben daher AQL pattern matching traversals eingeführt, die deutlich besser funktionieren sollte.

Sie könnten Ihre Abfrage wie folgt formulieren, die GRAPH_EDGES mit einem Traversal ersetzen:

FOR service IN TactiveService 
LET usesCommand = (
        FOR v, e IN 1..1 OUTBOUND service "TusesCommand" 
         FILTER e._from == service._id RETURN e 
    ) 
    LET command = DOCUMENT(usesCommand[0]._to) 
RETURN { service : service, usesCommand: usesCommand[0], command:command} 

Bitte beachten Sie, dass der angegebene Filter implizit ist true wegen wir für OUTBOUND Kanten von service beginnend abgefragt - so e._from wird immer gleich service._id sein. Anstatt GRAPH "topvision" zu spezifizieren und später die Kantensammlungen zu begrenzen, die wir im Traversal berücksichtigen wollen, verwenden wir die anonyme Graphabfrage nur unter Berücksichtigung der Kantensammlung TusesCommand, wie Sie es getan haben.

vereinfacht es also ein wenig mehr, könnte die Abfrage wie folgt aussehen:

FOR service IN TactiveService 
LET usesCommand = (
      FOR v, e IN 1..1 OUTBOUND service "TusesCommand" RETURN {v: v, e: e} 
    ) 
RETURN { service : service, usesCommand: usesCommand} 

Diese mehr Ecken als Ihre Abfrage zurückgeben kann, aber es wird sie nur einmal holen; Daher kann die Ergebnismenge größer sein, aber die Anzahl der Indexnachschlage wird durch die entfernten DOCUMENT Aufrufe der Abfrage reduziert.

Wie Sie bereits bemerkt und formuliert mit Ihrer zweiten Abfrage, wenn Ihr aktuelles Problem besser funktioniert mit einem classic join ArangoDB bietet Ihnen die Freiheit der Wahl, mit Ihren Daten so zu arbeiten.

bearbeiten: Michael ist das Richtige für Sie sicher, hat die Richtung OUTBOUND

+0

Danke, Ihre zweite Abfrage ist perfekt und so schnell wie das JOIN. –

3

wenn Sie aus irgendeinem Grund auf 2,8 aktualisieren wollen nicht sein, wie @dothebart vermuten lässt. Sie können auch die alte Abfrage reparieren.Ursprüngliche :

FOR service IN TactiveService 
    LET usesCommand = (
     return FIRST(GRAPH_EDGES("topvision", {}, { edgeExamples : [{_from: service._id}], edgeCollectionRestriction : "TusesCommand", includeData:true, maxDepth : 1 })) 
    ) 
    LET command = DOCUMENT(usesCommand[0]._to) 
RETURN { service : service, usesCommand: usesCommand[0], command:command} 

Der langsame Teil der Abfrage ist das Finden des Ausgangspunktes. Die API von GRAPH_EDGES verwendet den zweiten Parameter als Startbeispiel. {} passt zu allen Startpunkten. Daher berechnet es jetzt alle Ausgangs-Kanten für alle Stützpunkte zuerst (dies ist teuer, da dies tatsächlich für jeden Stützpunkt in der Anfangssammlung bedeutet, dass wir alle Kanten für jeden Stützpunkt in der Anfangssammlung sammeln). Dann filtert es alle gefundenen Kanten mit dem von Ihnen angegebenen Beispiel (wodurch fast alle Kanten wieder entfernt werden). Wenn Sie das Startbeispiel durch die _id des Startscheitelpunkts ersetzen, werden nur die Kanten für diesen bestimmten Scheitelpunkt erfasst. Jetzt sind Sie auch an den Kanten von nur einer Richtung interessiert (OUTBOUND), also können Sie es auch in den Optionen geben (so werden nur Kanten mit _from == service._id an erster Stelle von GRAPH_EDGES abgerufen).

FOR service IN TactiveService 
    LET usesCommand = (
     RETURN FIRST(GRAPH_EDGES("topvision", service._id, { edgeCollectionRestriction : "TusesCommand", includeData:true, maxDepth : 1, direction: 'outbound' })) 
    ) 
    LET command = DOCUMENT(usesCommand[0]._to) 
RETURN { service : service, usesCommand: usesCommand[0], command:command} 

Allerdings erwarte ich nach wie vor, dass die Version von @dothebart schneller in 2.8 ist, und ich würde auch auf die neueste Version zu wechseln empfehlen.

+0

Danke, service._id als Startpunkt anstelle von edgeExamples ist schneller (5 Sekunden statt 20 Sekunden). Ich benutze 2.8. –