Wie geschickt größere Datenmengen unterbringen?

Status
Nicht offen für weitere Antworten.

Jens81

Gesperrter Benutzer
Hallo zusammen,

ich habe folgendes (Performance) Problem:

Ich lese aus einer "Datenbank" (SAS Datei) via JDBC einige Datensätze aus (ca. 1,5 mio). Die Verbindung zur Datenbank sowie die SQL Abfrage laufen zügig durch. Nur wie speichere ich die Daten geschickt in meiner Java Anwendung. Bisher habe ich die Datensätze über eine while Schleife in einen Vector geschrieben. Das scheint allerdings nicht gerade ideal zu sein, da das Füllen ca. 30-40 Sekunden dauert.

Gibt es schnellere Datenstrukturen (LinkedList oder ArrayList haben keine entscheidende Verbesserung gebracht)? Oder bessere Methoden zum füllen? Oder irgendwelche anderen guten Ideen? Bin für alle Tipps und Vorschläge offen :)

Danke und Gruß,
Jens
 
S

SlaterB

Gast
teste mal, ob die Hälfte/ ein Zehntel der Datensätze proportional gleich viel Zeit benötigen
oder bedeutend schneller gehen,

ein bisschen kannst du dir sparen, indem du dem Vector/ der ArrayList am Anfang gleich mitteilst, wieviele Datensätze es sein werden (Konstruktor)
 

Jens81

Gesperrter Benutzer
Ich weiß leider vorher nicht, wieviele Ergebnisse zurückkommen. Von daher ist das mit der festen Größe leider nicht wirklich möglich.
Weniger Datensätze brauchen entsprechend weniger Zeit, grob gesagt pro 42.000 Datensätzen 1 Sekunde. Das schwankt allerdings, je nach Rechnerauslastung.
 
S

SlaterB

Gast
tja, so schlecht klingt das gar nicht, anderseits habe ich mal eben in einen Test-Programm 400.000 Dummy-Objekte in 0.2 Sek erzeugt,
was kann man da noch raten, hmm,

erzählt doch einfach möglichst genau mit Code, was alles bei einer Objekt-Speicherung passiert, muss nur ein Container-Objekt erstellt und dann Parameter übertragen werden
oder geschehen komplizierte Berechnungen, werden Strings erzeugt ("nr "+i), LogMeldungen ausgegeben, ..?

lasse JDBC und die restliche Anwendung weg, überlege dir einen Satz Testdaten und erzeuge daraus x00.000 identische Objekte und sammle diese in einer Liste, schneller?

wenn nicht, dann könntest du dieses Testprogramm zumindest posten ;)

wenn doch, durchlaufe das JDBC-ResultSet ohne die Daten umzuwandeln/ in der Liste zu speichern,
immer noch > 30 Sek? dann ist deine Liste wohl weniger das Problem
 
Zuletzt bearbeitet von einem Moderator:

sparrow

Top Contributor
Mach den Versuch mal ohne die Tupel in eine Collection zu speichern.
Quasi nur Datensätze des ResultSet durchlaufen ohne etwas damit zu tun, einfach um diese Stelle als Nadelöhr auszuschließen.
 

ARadauer

Top Contributor
du ließt während du füllst, oder? also für 1.5 mio Datensätze... 40 Sekunden.. finde ich jetzt echt human. ich kenn systeme die brauchen dafür 3 tage ;-)

zeig mal ein bisschen code...
 
Zuletzt bearbeitet:

robertpic71

Bekanntes Mitglied
Ich weiß leider vorher nicht, wieviele Ergebnisse zurückkommen. Von daher ist das mit der festen Größe leider nicht wirklich möglich.

Mir sagt jetzt SAS nichts, aber normalerweise kann man bei jeder Datenbank vorher den gleichen SELECT mit COUNT(*) machen und hat dann die Größe für die z.B. ArrayList.

/Robert
 
S

SlaterB

Gast
die genaue Anzahl ist auch nicht so wichtig,
wenn man auf paar MB Speicher verzichten kann, dann könnte man die ArrayList mit 3 Mio. inialisieren,
anderenfalls würden auch kleine Werte wie 100.000 bisschen helfen, selbst wenn es später 1.x Millionen werden

Hintergrund ist, dass die Liste sonst anfangs nur 16 Plätze hat, bei mehr Daten auf 32, 64, 128, .. vergrößert wird, vorhandene Daten müssen umkopiert werden,
so viel Aufwand ist das nicht, bei gerade mal 15 Verdopplungen ist man schon in den Millionen,
aber mit wenigen Zeichen Quellcode kann man da paar ms Zeit sparen

edit: statt verdoppelt, wird der Platz nur um 50% erhöht, zumindest bei ArrayList
 

Jens81

Gesperrter Benutzer
Hab mal ein kleines Testprog erstellt

Java:
public class Analyse {
	
	public void performTest() {
		Zeitmesser z0 = new Zeitmesser("Verbindung zu SAS aufbauen");
		Zeitmesser z1 = new Zeitmesser("Daten aus Tabelle holen");
		Zeitmesser z2 = new Zeitmesser("Daten in Vector schreiben");
		
		String tabelle = "test";
		String abfrage = "SELECT spalte FROM kundw." + tabelle + " WHERE flg = 0";
		Vector erg = new Vector();
		Connection verbindung;
		Statement statement;
		String pfad = "librefs=datModel 'pfad'";
		SASConnection sc = new SASConnection();
		
		z0.starteMessung();
		verbindung = sc.openDataConnection(pfad, "name", "pass");
		z0.beendeMessung();
		try {
			z1.starteMessung();
			statement = verbindung.createStatement();
			ResultSet result = statement.executeQuery(abfrage);
			z1.beendeMessung();
			
			z2.starteMessung();
			while (result.next()) 
			        erg.addElement(result.getString(1));
			
			
			z2.beendeMessung();
			

		}
		catch (Exception sql) {
			
		}
		
		System.out.println(erg.size());
	}
	
	public static void main(String[] args) {
		Analyse t = new Analyse();
		t.performTest();
	}
}

Mir sagt jetzt SAS nichts, aber normalerweise kann man bei jeder Datenbank vorher den gleichen SELECT mit COUNT(*) machen und hat dann die Größe für die z.B. ArrayList.

/Robert

Die Frage ist nur, ob der zusätzliche Aufwand eine Verbesserung bringt. Aber ich kann's ja mal testen.

EDIT: Das try catch in der Schleife war nur der Rest von nem Test, hab's entfernt..
 
Zuletzt bearbeitet:
S

SlaterB

Gast
das try/ catch in der Schleife kann weg,
ansonsten niemand das wirklich testen, lasse es selber ohne Vector durchlaufen
 

Jens81

Gesperrter Benutzer
Morgen zusammen,

hab das ResultSet durchlaufen lassen, ohne die Daten in den Vector zu schreiben. Siehe da, es läuft nicht schneller (oder zumindest nicht entscheidend). Von daher war euer Ansatz schonmal sehr gut :)
Stellt sich natürlich die Frage, wie das ResultSet schneller durchlaufen werden kann ???:L

EDIT: Selbst wenn ich in der while Schleife gar keine Anweisung mehr stehen habe, läuft diese > 30 Sekunden.

EDIT2: Der Falschenhals scheint result.next() zu sein. Nur was dagegen tun?
 
Zuletzt bearbeitet:

ARadauer

Top Contributor
ich denke du hast gar kein Problem... du ließt 1.5 Mio Datensätze aus einer Datenbank, wie schnell soll das gehen?

Liegt die Datenbank auf deinem Rechner? SAS? Was ist das, ich kenn das nicht... vielleicht geht das nicht schneller?
 

Jens81

Gesperrter Benutzer
Bis eben dachte ich, dass die Daten bereits komplett im ResultSet liegen. Es hat mich daher gewundert, warum das Durchlaufen so lange dauert und das es schneller gehen müsste.

Aber anscheinend ist es so, dass die Daten erst durch next() geladen werden...

Es hätte ja sein können, dass man an der Performance noch was machen kann :) 1x 40 Sekunden warten ist nicht so das Problem, aber wenn ich Zugriffe auf mehrere Tabellen ähnlicher Größe durchführen muss, wäre es inakzeptabel 15mins warten zu müssen :-/


PS: SAS steht für Statistical Analytic System (SAS | Business Analytics and Business Intelligence Software)
 
Zuletzt bearbeitet:

sparrow

Top Contributor
Morgen zusammen,

hab das ResultSet durchlaufen lassen, ohne die Daten in den Vector zu schreiben. Siehe da, es läuft nicht schneller (oder zumindest nicht entscheidend). Von daher war euer Ansatz schonmal sehr gut :)
Stellt sich natürlich die Frage, wie das ResultSet schneller durchlaufen werden kann ???:L

Das ResultSet wird genau so schnell durchlaufen wie die Datenbank die Tupel selektiert. Da ist also der Flaschenhals.
Ich weiß leider nicht was SAS ist... aber anscheinend nicht schnell.
Normalerweise funktioniert es so, dass du eine Anfrage an einen Server sendest und sich dann die Datenbank darum kümmert die möglichst schnell die Daten zur Verfügung zu stellen. Dafür ist die Datenbank ja da.
Wenn du unbedingt in eine Datei speichern willst empfehle ich dir Derby oder HSQLDB, mit denen habe ich sehr gute Erfahrung gemacht.

Gruß
sparrow
 

sparrow

Top Contributor
Jo, dafür sind die Daten, laut deiner Aussage, aber in einer Datei gespeichert und nicht etwa auf einem Datenbankserver der einen Datenbankdienst anbietet.
 

Jens81

Gesperrter Benutzer
Ja, die SAS Datenbank nutzt Dateien. Diese liegen auf dem Server.

Ich werde mal testen, ob mehrere Abfragen, die jeweils nur einen Teil der Daten selektieren und "parallel" laufen, eine bessere Performance zeigen.
 

ARadauer

Top Contributor
wäre es inakzeptabel 15mins warten zu müssen
also wie viele solche Tabellen hast du 20? dann reden wir von 30 Mio Datensätze.

30 Millionen Datensätze in 15 Minuten verarbeiten ist meiner Meinung nach schon akzeptabel ;-)

Was machst du eigentlich genau mit den Daten?
 

velaluka

Aktives Mitglied
Hallo,
wenn es doch anscheinend an dem JDBC Treiber liegt, würde ich mal nachsehen was dein SAS Treiber für Performance Tuning Möglichkeiten bietet. Eventuell kannst du so noch etwas rausholen.
Für Oracle würden mir dazu dazu die Stichworte
Batch, Prefetching und Transaktion Mode einfallen. Allerdings müsste diese Dinge schon implementiert sein.(Keine Ahnung ob der SAS Treiber sowas kann).
Oder eventuell einen Cache(z.B. EH-Cache) falls du wenigstens bei längeren Laufen der Appikation Performance Verbesserungen erreichen willst.

Ciao velaluka
 
Zuletzt bearbeitet:

sparrow

Top Contributor
Denke nicht, dass es dadurch schneller wird.
Ob nun sequentiell oder parallel, die Datensätze müssen trotzdem gefunden werden.
 

Jens81

Gesperrter Benutzer
Wenn ich die Daten über 5 Threads einsammle, kann ich die Zeit immerhin von zuvor zwischen 31 und 54 Sekunden (im Schnitt 36 Sek) auf 21-22 Sekunden drücken. Dabei verteile ich die Daten (noch) nicht gleichmäßig, dass werde ich mal im nächsten Schritt testen.

Der SAS JDBC Treiber unterstützt leider nichts in dieser Richtung, das habe ich schon versucht :)

edit: die Daten brauche ich für eine Data Mining Anwendung; diese speziell für ein Häufigkeitsdiagramm und die Verteilungsfunktion.
 
Zuletzt bearbeitet:

Jens81

Gesperrter Benutzer
Ein gleichmäßiges Verteilen der Datenmengen bringt einen geringeren Performanceschub. Die Thread-Lösung werde ich dann erstmal so in meine Anwendung integrieren.

Danke an alle für eure Ideen und Hilfestellungen!

Gruß, Jens
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben