2016-08-04 55 views
1

Wir verwenden ArangoDB und PostgreSQL, um fast identische Daten zu speichern. PostgreSQL wird verwendet, um allgemeine Arten von Abfragen durchzuführen, die relationale Datenbanken gut ausführen können. ArangoDB wurde ausgewählt, um eine Art von Abfragen wie Graph Traversals, Suche nach einem kürzesten Pfad usw.Wie verbessert man ArangoDB Leistung unter Last (mehrere gleichzeitige Abfragen)?

Im Moment haben wir eine Tabelle mit 160000 Datensätze in PostgreSQL und eine Sammlung mit der gleichen Anzahl von Dokumenten in ArangoDB.

Die API, an der wir arbeiten, wird von mehreren Benutzern gleichzeitig verwendet. Daher wollte ich zuerst überprüfen, wie ArangoDB und PostgreSQL unter der Last funktionieren. Ich habe einen einfachen Lasttest erstellt, der als Workload eine einfache Select-Abfrage mit dem Filter für ArangoDB und PostgreSQL durchführt.

Die Abfrage wählt die obersten N Datensätze/Dokumente mit dem Feld nach Datum filtern aus.

Wenn ich Lasttest ausführen, werden alle Anfragen an PostgreSQL innerhalb von 0,5 Sekunden ausgeführt, ich die Anzahl der Benutzer von 10 auf 100 erhöhen und die Ausführungszeit überhaupt nicht beeinflusst.

Die gleichen Anfragen an ArangoDB dauern ungefähr 2 Sekunden, wenn Sie mit einem einzelnen Benutzer beginnen, dann wächst die Antwortzeit im direkten Verhältnis zur Anzahl gleichzeitiger Benutzer. Bei 30 gleichzeitigen Benutzern würden alle Abfragen nach dem Warten auf 60 Sekunden für die Antwort eine Zeitüberschreitung aufweisen.

versuchte ich arangojs Anschluss zu debuggen und fanden diese:

var maxTasks = typeof agent.maxSockets === 'number' ? agent.maxSockets * 2 : Infinity; 

und diese:

Connection.agentDefaults = { 
    maxSockets: 3, 
    keepAlive: true, 
    keepAliveMsecs: 1000 
}; 

was bedeutet, dass Standard arangojs Verhalten bei der nicht mehr als 6 gleichzeitige Abfragen zu ArangoDB senden ist Dieselbe Zeit, die dazu führt, dass alle übrigen Abfragen auf Node.js Seite in die Warteschlange gestellt werden. Ich habe versucht, die Nummer zu erhöhen, aber es hat nicht geholfen und jetzt sieht es so aus, als ob alle Anfragen auf der Seite von ArandoDB in der Warteschlange stehen. Nun, wenn ich die Last leite und versuche, eine Abfrage mit ArangoDB Web Interface auszuführen, würde die Abfrage für die unvorhersehbare Zeit (abhängig von der Anzahl der Benutzer im Moment) reichen, dann das Ergebnis zurückgeben und würde mir zeigen, dass es ausgeführt wurde in ungefähr 4 Sekunden, was nicht wahr ist. Für mich sieht es so aus, als ob ArangoDB nur eine Abfrage pro Zeit ausführen kann, während alle anderen Abfragen in der Warteschlange stehen ...

Fehle ich etwas? Gibt es eine Einstellung, um ArangoDB einzustellen und seine Leistung unter Last zu verbessern?

Update:

Wir verwenden ArangoDB 3.0 und als Docker Behälter (von offiziellen Bild) laufen mit 1,5 GB RAM.

Beispieldokument (wir haben etwa 16 000 davon):

{ 
    "type": "start", 
    "from_date": "2016-07-28T10:22:16.000Z", 
    "to_date": "9999-06-19T18:40:00.000Z", 
    "comment": null, 
    "id": "13_start", 
    "version_id": 1 
} 

AQL Abfrage:

FOR result IN @@collection 
    FILTER (result.version_id == 1) 
    FILTER (result.to_date > '2016-08-02T15:57:45.278Z') 
    SORT result._key 
    LIMIT 100 
    RETURN result 
+0

Könnten Sie bitte Ihre Systemspezifikationen, die von Ihnen verwendete ArangoDB-Version und vielleicht ein Beispieldokument und die eigentliche Abfrage hinzufügen? – CoDEmanX

+0

Dem obigen Beitrag hinzugefügt. –

+0

mit 'db._explain (yourQuery)' verwenden Ihre Abfragen Indizes? Obwohl Sie die Ergebnismenge "LIMITIEREN", führt "SORTIEREN" dazu, dass alle Artikel überprüft werden müssen, nur das zurückgegebene Ergebnis ist begrenzt. Abhängig von der Ergebnisgröße Die verfügbare RAM-Menge ist möglicherweise etwas niedrig. Abhängig von den verfügbaren CPU-Ressourcen können mehr 'server.threads' helfen, die Geschwindigkeit zu erhöhen. – dothebart

Antwort

1

ich mit der folgenden Abfrage 160k Beispieldokumente erstellt:

LET v = [1,1,1,1,1,2,2,2,3,3,4] 
LET d = DATE_NOW() 

FOR i IN 1..160000 
INSERT { 
    "type": "start", 
    "from_date": DATE_SUBTRACT(d, RAND()*4000, "days"), 
    "to_date": DATE_ADD(d, RAND()*4000+100, "days"), 
    "comment": null, 
    "id": CONCAT(i, "_start"), 
    "version_id": v[RAND()*LENGTH(v)] 
} INTO @@collection 
RETURN NEW 

Bei der Synchronisierung mit der Festplatte beträgt die Datendatei ungefähr 30 MB. Die Journaldateien sind 32 MB groß.

Wenn Ihre Abfrage für dieses Dataset ausgeführt wird, beträgt die gemeldete Ausführungszeit im Durchschnitt 0,35 Sekunden.

Ich habe verschiedene Indizes ausprobiert und eine Skippliste auf nur version_id scheint die Leistung am besten zu verbessern, es auf 0,20 Sekunden auf Kosten von ~ 18MB Speicher für Indizes zu bringen. Direkt nach einem Neustart des Servers dauert die Abfrage 1,5 Sekunden, da die Sammlung beim ersten Zugriff geladen werden muss und die Indizes neu erstellt werden müssen. Nachfolgende Abfragen dauern jedoch 0.2s.

Ich verwendete ArangoDB 3.0.devel, die mehr oder weniger die gleiche Leistung wie die stabilen 3.0.x-Versionen zeigen sollte. Der vom DBMS verwendete Arbeitsspeicher betrug ~ 440 MB, nachdem die Abfrage je nach Webschnittstelle einige Male ausgeführt wurde.

Wenn Sie Abfragezeiten> 1,0s sehen, stimmt etwas nicht. Können Sie zwischen Abfragen überprüfen, wenn die Sammlung automatisch entladen wird (möglicherweise durch unzureichenden RAM)? Wenn ja, überprüfen Sie, was Ihren Speicher frisst (wenn es sogar ArangoDB ist), und stellen Sie sicher, dass Sie mit mehr RAM versuchen, um zu sehen, ob es die Abfragezeit beeinflusst. Könnte eine andere Ressource die Leistung einschränken, z. B. den Massenspeicher oder die CPU?

+0

Ja, ich kann fast die exakte Geschwindigkeit wiedergeben, wie Sie es auf meinem PC beschrieben haben. Beachten Sie jedoch, dass Sie die Leistung einer einzelnen Abfrage beschreiben, während ich nach der Geschwindigkeit von Abfragen unter Last gefragt habe. Also, wenn ich die gleichen Beispieldaten verwende, wie du es tust, dann führe meinen Belastungstest mit diesen Daten aus. Ich bekomme normale Leistung mit einem einzelnen Benutzer, aber wenn die Anzahl der Benutzer wächst, wächst auch die Antwortzeit. Hier ist, wie es aussieht (beachten Sie, wie schneller PostgreSql Antwortzeit ist): https://cloud.mail.ru/public/3yyY/joAXFwxVD –