Schnellste Möglichkeit Datenverarbeitung

Status
Nicht offen für weitere Antworten.

The_S

Top Contributor
Hi,

ich habe eine Portalanwendung. In dieser Portalanwendung kann über eine JSP ein Excel-Servlet (JXL) aufgerufen werden. Dieses Servlet ist zur Darstellung des Ergebnisses einer Stored Procedure zuständig. Dabei handelt es sich aber um sehr viele Daten (Die SP benötigt alleine ca. 30 Sekunden). Diese Daten müssen aber noch gewissermaßen aufgearbeitet und verwertet werden. Dazu suche ich jetzt die schnellste Möglichkeit. Am Besten stelle ich den Sachverhalt mal vereinfacht dar.

- Es gibt Kunden, Artikel und Farben. Jeder Kunde kann mehrere Artikel haben, jeder Artikel mehrere Farben.
- Ein ResultSet der Stored Procedure enthält den Kunden, einen Artikel und eine Farbe dieses Artikels
- Ein ResultSet ist zuerst nach Kunden, und innerhalb nochmal nach Artikeln sortiert
- Am Ende des Excel-Sheets muss eine Stückzahl je Artikel (Farben je Artikel aufaddiert) und ohne Rücksicht auf Kunden ausgegeben werden

Beispielaufbau des ResultSet:

kdnr:1,art:10,farbe:grün
kdnr:1,art:10,farbe:rot
kdnr:1,art:13,farbe:rot
kdnr:2,art:11,farbe:blau
kdnr:2,art:12,farbe:grün
kdnr:2,art:12,farbe:blau
kdnr:3,art:10,farbe:rot

etc.

Beispielaufbau des ExcelSheets:

kdnr:1
art:10
farbe:grün
farbe:rot
art:13
farbe:rot
kdnr:2
art:11
farbe:blau
art:12
farbe:grün
farbe:blau
kdnr:3
art:10
farbe:rot

art:10 - 3
art:11 - 1
art:12 - 2
art:13 - 1

etc.

Meine Frage ist, wie ich diese Darstellung mit möglichst geringen Resourcen-Verbrauch darstellen kann. Meine jetztige Implementierung sieht 3 Klassen vor. Kunde, Artikel und Farbe. Ein Kunde hat u. a. eine ArrayList mit Artikeln und ein Artikel hat u. a. eine ArrayList mit Farben. Im Servlet selbst gibt es eine ArrayList von Kunden. Ich gehe jetzt also das ResultSet durch. Bei jedem Datensatz erstelle ich zuerst ein Kunden-Objekt und überprüfe, ob das schon in der ArrayList existiert. Ist dies nicht der Fall, wird das Kunden-Objekt der ArrayList hinzugefügt. Existiert das Kunden-Objekt bereits, wird überprüft, ob der Artikel des Datensatzes schon im Kunden-Objekt existiert. Ist dies der Fall, wird zu diesem Artikel die Farbe aus dem Datensatz hinzugefügt. Ist dies nicht der Fall wird der komplette Artikel der ArrayList für Artikel des Kunden neu hinzugefügt.

Funktionieren tuts, nur ist es verdammt langsam. Dauert ca. zwischen 3 und 5 Minuten + die 30 Sekunden der Stored Procedure bei 27783 Datensätzen. Und dabei ist die Excel-Generierung noch nicht mal mit eingerechnet!

Also wenn jemand einen Tipp für mich hätte, wie ich das Ganze performanter gestalten kann, würde ich mich freuen. Das Ganze kann auch ruhig dirty und nicht oop sein, ist nur ein kleines Auswertungsportlet, das niemand mehr nach dem Deployen ansehen wird 😉 .

lg
 
gehe ich recht in der Annahme, dass das ganze mit Excel, Stored Procedures und Servlet nix zu tun hast,
dass du nur die reine Java-Objekt-Verarbeitung meinst?

dann ist es ganz schön müsam, 50% deines Posts mit diesen Nebenthemen auszusortieren..

also, um 30.000 Objekte zu erzeugen und bisschen rumzuschubsen solltest du keine nennenswerte Zeit benötigen,
ohne Code kann man dazu aber wenig sagen,

nur das Prüfen des Vorhandensein eines Objektes in der großen Liste ist ein Punkt, den man streichen kann,
verwende eine Map, das geht zigmal schneller,

bei Farbe zu Artikel kannst du vielleicht gar direkt eine Map der Artikel aufbauen,
unabhängig davon, zu welchem Kunden der Artikel gehört
 
Hi, danke für die Antwort 😀

SlaterB hat gesagt.:
gehe ich recht in der Annahme, dass das ganze mit Excel, Stored Procedures und Servlet nix zu tun hast, dass du nur die reine Java-Objekt-Verarbeitung meinst?

jain 😉 . Servlet und Stored Procedures waren eher ein Zusatz, um meine Ausgangslage zu verdeutlichen. Ob die Daten jetzt aus ner Datenbank, Datei oder sonstwo herkommen ist prinzipiell egal. Aber die Darstellung als Excel ist schon wichtig. Die Daten müssen später nicht weiter verarbeitet werden. Ich muss sie nur möglichst schnell in diesem Format darstellen können.

SlaterB hat gesagt.:
dann ist es ganz schön müsam, 50% deines Posts mit diesen Nebenthemen auszusortieren..

Sorry, StoredProcedures und Servlet hät ich mir sparen können, aber der große Teil (Excel) ist ja schon wichtig ...

SlaterB hat gesagt.:
also, um 30.000 Objekte zu erzeugen und bisschen rumzuschubsen solltest du keine nennenswerte Zeit benötigen, ohne Code kann man dazu aber wenig sagen,

Code liegt im Workspace auf Arbeit, werd am Montag mal was posten.

SlaterB hat gesagt.:
nur das Prüfen des Vorhandensein eines Objektes in der großen Liste ist ein Punkt, den man streichen kann, verwende eine Map, das geht zigmal schneller,

Mittlerweile bin ich auf die Idee gekommen einfach nur den letzten Kunden, Artikel und Farbe zu hinterlegen, da die Tabelle ja ohnehin sortiert ist. Die Gesamtwerte werden dann in ein, zwei Variablen einfach aufaddiert. Inwieweit das machbar ist, werde ich am Montag Vormittag prüfen!

SlaterB hat gesagt.:
bei Farbe zu Artikel kannst du vielleicht gar direkt eine Map der Artikel aufbauen,
unabhängig davon, zu welchem Kunden der Artikel gehört

Hätte ich dann nicht irgendwo Datenredundanz, was das Ganze nochmal verlangsamt?
 
Also, ich bin jetzt dazu übergegangen die Objekte nicht in einem Array zu speichern, sondern aufgrund der Sortierung immer nur das jeweils letzte und dann vergleichen. Des weiteren habe ich für die Gesamtsumme am Ende eine weitere StoredProcedure angelegt.

Mein Code zur Excel-Generierung sieht nun wie folgt aus:

Code:
				while (rs.next()) {
					if (!rs.getString("KDNR").startsWith("*")) {
						temp = new Kunde(Integer.parseInt(rs.getString("KDNR").trim()));
						if (last.equals(temp)) {
							tempA = new Artikel(rs.getString("KBSN"));
							drawArtSpez(pos, sheet, rs.getString("FOBZ").trim(),
								rs.getString("FBNR").trim(),
								rs.getDouble("EPRS"),
								rs.getDouble("BPRS"),
								rs.getInt("PSMG"),
								rs.getDouble("EKWR"),
								rs.getDouble("WAWR"));
							if (lastA.equals(tempA)) {
								pos++;
							}
							else {
								lastA = new Artikel(rs.getString("KBSN"));
								drawArt(pos, sheet, lastA.getArtnr());
								pos++;
							}
							kstk += rs.getInt("PSMG");
							kek += rs.getDouble("EPRS");
							kvk += rs.getDouble("BPRS");
							kekg += rs.getDouble("EKWR");
							kvkg += rs.getDouble("WAWR");
						}
						else {
							if (last.getKdnr() != 0) {
								drawZWSK(pos, sheet, local, kek, kvk, kstk, kekg, kvkg);
								pos++;
							}
							pos++;
							lastA = new Artikel(rs.getString("KBSN"));
							last = new Kunde(Integer.parseInt(rs.getString("KDNR").trim()),
									rs.getString("KNM1").trim(),
									rs.getString("KNM2").trim(),
									rs.getString("KSTR").trim(),
									rs.getString("PLZL").trim(),	
									rs.getString("KORT").trim(),
									lastA);
							addHead(pos, sheet, local, last.getKdnr(), last.getKdnm1() + ", " + last.getKdnm2() +
											", " + last.getStr() + ", " + last.getPlz() + ", " + last.getOrt());
							pos += 4;
							drawArt(pos, sheet, lastA.getArtnr());
							drawArtSpez(pos, sheet, rs.getString("FOBZ").trim(),
									rs.getString("FBNR").trim(),
									rs.getDouble("EPRS"),
									rs.getDouble("BPRS"),
									rs.getInt("PSMG"),
									rs.getDouble("EKWR"),
									rs.getDouble("WAWR"));
							pos++;
							kstk = rs.getInt("PSMG");
							kek = rs.getDouble("EPRS");
							kvk = rs.getDouble("BPRS");
							kekg = rs.getDouble("EKWR");
							kvkg = rs.getDouble("WAWR");
						}
					}
				}

temp/last und tempA/lastA enthalten jeweils die Referenzen auf die aktuellen Kunden und Artikel. die k-variablen zählen die positionen für einen Kunden mit, da diese für jeden Kunden ausgegeben werden müssen. Die Methoden, die aufgerufen werden, sind lediglich für das Schreiben des Excel-Files zuständig, also hier nicht relevant.

Für Verbesserungsvorschläge/Anregungen wäre ich dankbar!

lg
 
kstk += rs.getInt("PSMG");
kek += rs.getDouble("EPRS");
....
last.getKdnm1() + ", " + last.getKdnm2() + ", " + last.getStr() + ", " + last.getPlz() + ", " + last.getOrt()


klingt etwas gefährlich, werden da Strings nach und nach aufgebaut?
da ist ja StringBuilder sehr sehr viel besser, auf wenn der Aufwand groß erscheint,

ansonsten ist nicht gerade klar ersichtlich was da so abläuft,
für welche der 30.000 Daten ein if oder ein else durchlaufen wird usw,

aber das prüfst du besser auch selber nach,
fange einfach an, indem du nur 30000x "Test" irgendwoher ausliest (und sei es zum testen eine statische Variable) und in dein Excel schreibst,
nach und nach die einzelnen Schritt hinzufügen, wie 'mehr Daten', Zwischenobjekte erzeugen, Vergleiche usw.

mit etwas Glück, siehst du wie an einzelnen eigentlich trivialen Schritten wie
addHead(pos, sheet, local, last.getKdnr(), last.getKdnm1() + ", " + last.getKdnm2() +
", " + last.getStr() + ", " + last.getPlz() + ", " + last.getOrt());
statt
addHead(pos, sheet, local, last.getKdnr(), last.getKdnm1());

die Bearbeitungszeit ungewöhnlich ansteigt, dann kannst du das genauer untersuchen

(fertig mit der Allgemeinpredigt 😉 )
 
Hi, sorry dass ich dich jetzt hier bemüht habe 😳 . kA warum, aber mein Testserver braucht für eine Operation ca. 15 Minuten, für die selbe Operation braucht unser wirklicher Server nicht mal eine Minute, wovon schon mehr als die Hälfe für die Datenbankabfrage drauf geht. Insgesamt hat sich das Problem also verflogen 😉 .

Da die Strings max. 15 Zeichen lang werden, sah ich es nicht für erheblich auf einen StringBuffer auszuweichen.

Aber danke für deine Hilfe!
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben