Bin eben am entwickeln eine WebApplikation, welche Daten aus einer DB2-SQL Datenbank auf einer AS400 ausläd. Das Problem ist, dass ab einer gewissen Datengrösse die Zugriffszeit extrem wird. Zu diesem Zweck hab ich mir bereits einen Serverseitigen Cache gebaut, bringt jedoch keine merkenswerte Gewinne. Demnach ist es definitif nicht der SQL-Select welcher den Flaschenhals darstellt. Das Netzwerk kann ich auch ausschliessen.
Meine Vermutung ist, dass es etwas mit der Umwandlung der Daten oder einem Problem mit Stack/Heap (ev. auch Swap) zu tun hat…
Irgend eine Idee hierzu, oder wie ich das Problem elegant umgehen kann?
Hast Du’s schon mal mit einem Profling-Tool versucht?
So könntest Du rasufinden wo du Zeit und Speicher verbrauchst.
Nun, wo die Zeit verbraten wird, ist halt beim SQL Select Statement. Die Frage ist halt, wo genau. Denn dieser Aufruf geht ja übers Netz auf den Server, dort wird er in die SQL-Datenbank abgesetzt. Das Resultat Javalike umgewandelt übers Netz wieder an den PC zurück gesandt. Dies kann ich jedoch nicht mit Profling Tools zerlegen, deshalb meine Frage…
Anschliesende Auswertung ist nicht mehr betroffen…
dann siehts aber so aus ob das sql statement schlecht ist. die
jdbc geschichte ist performant.
hast du die möglichkeit das statement zu analysieren?
? Versteh ich jetzt nicht so ganz…
Also, das Statement greift auf eine logical view zu, bestehend aus 6 Feldern. Aus diesen werden dann 3 ausgewählt, und sämtliche Records von 60000 bis 69999 zwecks Auswahl hochgeladen. Anschliesend sollen dann aus diesem Inhaltsverzeichnis einzelne zwecks Detailsicht ausgewählt werden.
Also, das Statement greift auf eine logical view zu, bestehend
aus 6 Feldern. Aus diesen werden dann 3 ausgewählt, und
sämtliche Records von 60000 bis 69999 zwecks Auswahl
hochgeladen. Anschliesend sollen dann aus diesem
Inhaltsverzeichnis einzelne zwecks Detailsicht ausgewählt
werden.
Ok. Und welcher Teilschritt dauert jetzt am längsten?
Die Ausführung der View
Die Uebertragung der Daten von der DB zur Applikation
Das Anzeigen im GUI
Hast Du die View schon mal ausgeführt und gemessen wie lange das dauert?
Dieser Schritt ist zu vernachlässigen, den kann ich dadurch ausschliesen, dass ich mir ein DatenCache gebaut hab, welches das eigentliche Select nur nach einer vorgegebenen ExpirationTime in die DB ausführt. Läge es also am Select, müsste ich ab dem 2. Zugriff, welcher ja aus dem Cache lädt, eine merkliche Steigerung erfahren. Tut es jedoch nicht. Somit muss das Problem daran liegen, dass der Server (WebSphere) eine grössere Datenmenge an den Client sendet. Meine Vermutung geht halt dahin, dass Java hier ein Problem mit der Datengrösse hat…
Wie könnte ich das Problem denn noch weiter eingrenzen?
[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]
Du solltest mal rausfinden, wieviele Daten du vom Server an
den Client sendest.
Wie gesagt, sind etwa 10000 Records, pro Record weniger als 100 Byte.
Genaue Zahl ist nicht zu ermitteln, da das Ganze aus einer DB stammt, welche sich permanent verändert. Die Zahl ist jedoch die Obergrenze. Als Mittelwert sind es wohl etwa 6k-7k Records
Dazu noch einige Fragen:
Musst alle Daten auf einmal übertragen oder könntest du für
die Datailansicht (oder was auch immer) nochmals einen
Serverzugriff machen.
Sorry, hab mich missverständlich ausgedrückt… Diese Daten SIND die Detailansicht. Anschliessend werden diese als Schlüssel benutzt um die darunter liegende (andere View/Tabelle) zu laden. Hier gibts dann etwa 100 Felder pro Datensatz/Schlüssel.
Werden die Daten vom Client aufbereitet oder sendet der
Server gleich die fertigen Objekte?
?Bin mir nicht ganz sicher wie ich das jetzt verstehen soll? Also, da Java auf dem Server läuft, findet zumindest die Konvertierung von DB2 in Java Result Set statt… Dieser wird dann zum Client gesandt
Welche Kommunikation hast du? (IIOP, HTTP, JMS?)
Em, ???
Client hat http in einem Browser. Dort mittels servlets zugriff auf DB…
Ich hab mal aus dem Code die relevanten Stellen rausgeschnitten und entsprechend aufbereitet, eventuell liegt ja hier der Hund begraben.?
public void init(javax.servlet.ServletConfig config) throws javax.servlet.ServletException
{
try
{ MF\_Configuration.registerDriver(); }
catch (java.lang.Exception e)
{ throw new javax.servlet.ServletException("Could not locate database server!!!"); }
}
--------
public static void registerDriver() throws Exception
{
java.lang.String l\_driverName = null;
java.sql.Driver l\_driver = null;
try //as long as any of the required drivers are registered, remove those
{ while (true)
{ l\_driver = java.sql.DriverManager.getDriver("jdbc:db2:\*local;prompt=false");
java.sql.DriverManager.deregisterDriver(l\_driver);
}
} catch (Exception e)
{ ; //Do nothing, end of loop
}
l\_driver = (java.sql.Driver)(Class.forName("com.ibm.db2.jdbc.app.DB2Driver").newInstance());
java.sql.DriverManager.registerDriver(l\_driver);
}
--------
**Eigentlicher Code:**
java.sql.Connection l\_conn = java.sql.DriverManager.getConnection("jdbc:db2:\*local;prompt=false", d\_LoginName, d\_PassWord);
java.sql.ResultSet l\_ResultSet = null;
try
{ l\_ResultSet = l\_conn.createStatement
( java.sql.ResultSet.TYPE\_SCROLL\_INSENSITIVE,
java.sql.ResultSet.CONCUR\_READ\_ONLY).executeQuery
**an der folgenden Zeile hängts (Zeitaufwendig)**
( " _Select Field1, Field2 from Data.Base where Field1 \>= 60000 and Field )
);
} catch (java.sql.SQLException e)
{}_
Hast Du den Select mal direkt auf die DB ausgeführt?
Ja, dort gibt es keine Probleme, doch dies hab ja auch eigentlich dadurch ausgeschlossen, dass ich das eigentliche Select mittels selbst gebautem Cache (nicht im angezeigten Code enthalten) eliminiert hab. Die Client-seite bekommt davon jedoch nix mit, sprich identische Daten werden in beiden Fällen übers Netz gesandt. Deshalb der entsprechende Code. Doch wie bereits erwähnt bringt das nichts, somit schliesse ich die DB/Select aus
Noch ne weitere Idee? Oder ist Java bekannt dafür Probleme mit grösseren Datenmengen zu haben?
Das was Du hast sind ja auch keine grösseren Datenmengen!
Ich kann mir wirklich nicht vorstellen wo das Problem liegen könnte.
Hast Du die Möglichkeit auf WebSphere das Profiling-Tool zu gebrauchen oder sonst die Zeit zu messen welche bei den einzelnen Methodenaufrufen verloren geht?
Ansonsten ist es für mich halt schwierig was rauszufinden.