2016-04-02 9 views
2

Meine Datenbank hat folgende "Schema":Social network-ish Abfrage in ArangoDB

  • BenutzerAutorBeiträge
  • BenutzerwieBeiträge

Meine bescheidenen Testdatenbank enthält:

  • 162 Benutzer
  • 442 Beiträge
  • 159 mag

Nun möchte Ich mag die beliebtesten Benutzer abzufragen, welche die Benutzer, die gesammelt haben, die die meisten Likes in allen ihren Beiträgen. Ich kam mit der folgenden Abfrage auf:

FOR u IN users 
    LET nblikes = SUM(FOR post IN 1 OUTBOUND u isAuthor 
     RETURN LENGTH(GRAPH_EDGES('my-graph', post, { edgeCollectionRestriction: 'likes' }))) 
    SORT nblikes DESC 
    RETURN { 
     "username": u.username, 
     "nblikes": nblikes 
    } 

, die in etwa 0,8 s auf meiner Mitte 2014 führt MacBookPro (2,8 GHz Core i7, 16 GB RAM). 0.8s ist nicht beschämend, aber auf solch einem kleinen Datensatz hätte ich besser erwartet, dass, AFAIK, alles in Erinnerung ist.

So würde ich mich freuen, wenn einige ArangoDB Gurus da draußen meine Abfrage überprüfen und einige potenzielle Leistungsprobleme hinweisen könnten. Danke vielmals!

+0

Wie schnell ist Ihre Abfrage, wenn Sie die vorgeschlagene Graph Traversal verwenden, und wie schnell ist es mit einem Join? Vielen Dank! – CoDEmanX

Antwort

3

Es gibt einige Möglichkeiten, diese Abfrage schneller auszuführen.

Was wird sich verbessern sie am meisten dem inneren Ruf zu GRAPH_EDGES mit anderen Traversal der Tiefe 1 Ersetzen der „likers“ zu finden, wie unten dargestellt:

FOR u IN users 
    LET nblikes = SUM(
    FOR post IN 1 OUTBOUND u isAuthor 
     RETURN LENGTH(
     /* the following traversal replaces the call to GRAPH_EDGES */ 
     FOR liker IN 1 INBOUND post._id likes 
      RETURN 1 
    ) 
) 
    SORT nblikes DESC 
    RETURN { 
    username: u.username, 
    nblikes: nblikes 
    } 

Die innere Funktionsaufruf GRAPH_EDGES recht teuer ist, und Wenn Sie es loswerden, wird sich die Ausführungszeit der Abfrage erheblich verbessern.

Eine andere Variante besteht darin, die (jetzt) ​​zwei Überquerungen mit einem einfachen Join wie folgt zu ersetzen:

FOR u IN users 
    LET nblikes = SUM(
    /* the following join between users, isAuthor and likes 
     replaces the traversal & GRAPH_EDGES calls */ 
    FOR a IN isAuthor 
     FILTER a._from == u._id 
     FOR l IN likes 
     FILTER l._to == a._to 
     RETURN 1 
) 
    SORT nblikes DESC 
    RETURN { 
    username: u.username, 
    nblikes: nblikes 
    } 

Beide Varianten schneller sein sollte als die erste Abfrage, vor allem, weil GRAPH_EDGES teuer ist in einer Schleife zu nennen. Da es sich um eine zustandslose AQL-Funktion handelt, muss es seinen Kontext wiederholt einrichten (so oft es aus der inneren Schleife aufgerufen wird). Die Traversalen und die Joins-Lösung können etwas mehr Kontext zwischen den Anrufen behalten, so dass sie "billiger" sind.

+0

Danke! Was sind also gute Anwendungsfälle für GRAPH_EDGES? – ThomasWeiss

+0

Sie können 'GRAPH_EDGES' als Konstrukt auf oberster Ebene verwenden, nicht innerhalb von Schleifen. Ein eindeutiger Indikator dafür ist, wenn Sie es mit "LIMIT" kombinieren wollen - das macht keinen Sinn. – dothebart