Hallo,
ich habe Performance-Probleme mit einer bei uns entwickelten Java-Anwendung. Die Anwendung läuft parallel (ca 80 Prozesse) auf mehreren Nodes eines Computerclusters, alle diese Prozesse berechnen Daten und schreiben diese recht häufig in kleinen Portionen per JDBC auf einen zentralen DB-Server (PostgreSQL 9.3 auf OpenSuSE, 12cores, 16GB RAM und config gemäß dem Artikel Tuning Your PostgreSQL Server daran angepasst, auch an die Anzahl der Verbindungen).
Anfangs ist die Performance der Prozesse gut, aber nach ein paar Stunden Berechnungszeit wird sie schlechter, solange noch alle Prozesse laufen. D.h., die Prozesse brauchen immer länger (anfangs 2 Minuten, am Ende mehr als 30 Minuten). Ich habe die Prozesse remote geprofiled, und sie verbringen ihre Zeit mehr und mehr in den Methoden, die in die DB schreiben (sie machen dann auch kaum noch CPU-Load auf ihren Nodes, da sie anscheinend nur warten). Das Load auf dem DB-Server ist aber ok laut Ganglia (~50% CPU-idle), Platte, Memory und Netzwerk auch im grünen Bereich, und bei dem Server sollte es auch so sein. Das Load auf dem DB-Server ändert sich auch nicht, wenn die Prozesse langsamer werden.
Die Indizes in der DB sind anscheinend passend gesetzt: denn wenn ich die Prozesse abbreche, die Datenbank aber so voll lasse, und dann manuell einen einzelnen Prozess starte, geht es auf einmal wieder schnell. Also braucht das Eintragen anscheinend nicht deshalb lange, weil der Server lange Sachen ohne Index suchen muss, die immer mehr werden, während die Daten dazukommen (denn der Index sowie der Füllstand der DB ändern sich ja durch das Abbrechen der anderen Prozesse auch nicht, es sollte also dann immer noch langsam sein). Bei fehlenden/falschen Indizes sollte der DB-Server außerdem rechnen wie blöde, also CPU-idle sehr nah an 0% haben (und nicht ~50%).
Mir scheint es eher an zu häufigem Commiten in der Anwendung zu liegen: in der Anwendung ist auto-commit für die Connection an und es werden sehr häufig sehr kleine Daten in die DB geschrieben (z.B. viele Einträge in n:m-Auflösungs-Tabellen, die nur 2 IDs pro Eintrag enthalten). Kann das das Problem sein?
Ich habe daher 2 Fragen:
1) Wie sollte ich vorgehen, um das Problem aufzuspüren? (Loggen lange dauernder Queries? Kann ich irgendwie feststellen, ob es am Commiten liegt?)
2) Macht es Sinn, in der Anwendung auto-commit auszustellen für die Verbindung, und nur wenige Male manuell zu commiten? (Momemtan, mit auto-commit an, wird in der Laufzeit von ca 2 Minuten bestimmt über 100 mal auto-committed, denke ich).
Vielen Dank für Vorschläge,
Tim