# Welche Persistenz für große Datenmengen?



## Sandra Haupt (4. August 2004)

Hallo,

ich benutze derzeit eine MySQL Datenbank und habe festgestellt, dass sie ein richtiges Nadelöhr für meine Performance ist. Ich muss oftmals Zehntausende von Datensätzen auslesen oder verändern und suche nun eine geeignete Speichermöglichkeit. Dabei stieß ich auf JDO und FastObjects von der Firma Poet. Leider  habe ich beim ersten Überlesen der Features den Eindruck bekommen, dass sich FastObjects nicht nur auf festgelegte Standards verläßt, sondern auch eigene Möglichkeiten anbietet. Ich möchte mich aber nicht durch die Verwendung von Nicht-Standardbefehlen auf FastObjects festlegen, sondern suche mehr eine Open Source Standart Objekt Datenbank, wie sie jetzt wohl vom Jakarta Projekt  in der Entwicklung ist.

Welche Speichermethode würdet ihr mir empfehlen für große Datenmengen und einer objektbezogenen Speicherart?

Danke, Sandra


----------



## squeaker (4. August 2004)

Persistenz ist meiner Meinung nach die Fähigkeit Änderungen nachzuvollziehen bzw. Rückgängig zu machen und zu Branchen. Ich hatte das so gelernt: keine Persistenz der Daten - keine Änderungen rückgängig machen. Semi-Persistent: Änderungen rückgängig machen aber keine Branches. Volle Persistenz: im Prinzip wie CVS - an beliebigen Stellen verzweigen usw.

Was das allerdings mit deiner Frage zu tun hat, weiss ich nicht.


----------



## RedWing (4. August 2004)

@squeaker:
"Persistenz = dauerhaftes Speichern von Daten auf einem externen Datenträger
                    so das diese auch nach dem Beenden des Programms erhalten bleiben"

@Sandra
Also soviele Möglichkeiten gibts da meines Erachtens nicht. Entweder du benutzt
eine DB für die persistente Speicherung deiner Daten, oder du 
verwendest das Streaming(File IO) der Java API, was allerdings bei großen
Datenmengen relativ schnell unübersichtlich werden kann.
Wenn du nach Open Source Datenbankenaltenativen suchst kann ich dir
sourceforge.net empfehlen.
Mit dem Suchwort database findest du eine Menge Suchergebnisse.

Gruß

RedWing


----------



## Thomas Darimont (4. August 2004)

Hallo!

Eigentlich sollte MySQL auch mit dieser Datenmenge zurecht kommen.
Ein Flaschenhals bei der DB kann viele Ursachen haben. Ungünstiges Datenbank Design (keine Indizierung,  unvorteilhafte Abfragen), alter JDBC Treiber oder dessen unsachgemäße Verwendung. 

Verwendest du PreparedStatements? Batch Updates? Hast du Abfragen mit sehr vielen Joins?

Das sind dann im Allgemeinen die Stellschrauben an denen man drehen kann.
Also erstmal danach schauen, bevor man sich an andere Technologien heranwagt.

@squeaker: -> http://de.wikipedia.org/wiki/Persistenz

Gruß Tom


----------



## Sandra Haupt (4. August 2004)

Hallo,

@RedWing 
Danke für den Link.

@Tom
Ich stimme dir zu, dass die MySQL Datenbank mit der Menge an Daten fertig wird. Ich habe mit PHP auch keine Probleme. Unter Java geht die Performance aber deutlich nach unten. Ich vermute das liegt daran, dass ich meine objektorientierte in eine relationale Struktur umwandeln muss. Z.B. muss ich mein Objekt erst in mehrere Tupel umwandeln, danach muss ich SQL Befehle zum Abspeichern schreiben, umgekehrt beim Laden genauso. Ausserdem möchte ich ab und an Objekte cachen, ich muss also das objektbezogene Caching mehreren relationalen Tabellen zuordnen, was den Code nicht  einfacher macht.

Kurz gesagt, um in MySQL etwas abzuspeichern oder daraus etwas zu laden ist ein sehr großer Overhead erforderlich, der meiner Meinung nach die Bremse ist.  Ich suche nun eine Persistenz, bei der nicht diverse Umwandlungen notwendig sind, sondern bei der ich gleich meine Objekte speichern kann und bin gerne bereit dafür auch neue Techniken zu erlernen.

P.S. Ich nutze den neusten  JDBC Treiber von der MySQL Homepage.

Grüße, Sandra


----------



## squeaker (4. August 2004)

machst du viele Objekte und löschst sie danach wieder? das ist unter Java sehr langsam. Vielleicht kannst du dir einen Objekt-Pool bauen. Die Objekte werden erstellt und wenn sie nicht mehr benötigt werden, werden sie zurück in den Pool gestellt. Falls nun ein neues Objekt benötigt wird, holt man sich eines aus dem Pool und setzt nur die Daten neu. So müssen die einzelnen Objekte nicht stets neu erstellt werden, Speicher alloziert werden ...  und am Ende wieder zerstört werden.

Ich hoffe das hilft. Schau dir auch mal dein Java-Programm mit einem Profiler an. Der kann dir sagen in welchem Teil deines Programmes am meisten Zeit vertrödelt wird.


----------



## Valentin- (4. August 2004)

> _Original geschrieben von squeaker _
> *machst du viele Objekte und löschst sie danach wieder? das ist unter Java sehr langsam. Vielleicht kannst du dir einen Objekt-Pool bauen. Die Objekte werden erstellt und wenn sie nicht mehr benötigt werden, werden sie zurück in den Pool gestellt. Falls nun ein neues Objekt benötigt wird, holt man sich eines aus dem Pool und setzt nur die Daten neu. So müssen die einzelnen Objekte nicht stets neu erstellt werden, Speicher alloziert werden ...  und am Ende wieder zerstört werden.
> 
> Ich hoffe das hilft. Schau dir auch mal dein Java-Programm mit einem Profiler an. Der kann dir sagen in welchem Teil deines Programmes am meisten Zeit vertrödelt wird. *



Das mit der Overhead würde ich nicht unterschreiben halte ich für fraglich.
Das war damals bei 1.1. so, aber seit der HotSpot VM und der relational GC
ist das nicht mehr so der Fall.

@ Sandra:
Mal Ibatis oder Hibernate angeschaut?
Einfach mal nach googlen gibt es links ohne Ende dazu!

Ciao


----------



## Cybernd (5. August 2004)

Peristenz: Besagt lediglich das etwas außerhalb des Programlebenszyklus erhalten bleibt. Hat also nichts mit Branches & Co an sich zu tun.

JDO: Momentan wohl der neue Standard der Persistierung. Vielleicht ein Standard mit dem Potential, irgendwann mal JDBC ersetzen zu können. Im Grunde genommen die Weiterentwicklung von ODMG, nur das JDO im Gegensatz zu ODMG von der Wirtschaft akzeptiert wird.

Warum JDO anstelle von SQL basierten Datenbanken? Simpel: Weil der Programmierer nicht in SQL / Tupeln denken will. Der Programmierer will ausschließlich mit Objekten arbeiten und gerade hierfür ist JDO gebaut worden. Es ist zudem so ausgelegt worden das man dahinter sowohl relationale als auch objektorientierte Datenbanken pappen kann.

Die Versant DB ist im übrigen eine solche Objektdatenbank. Im Grunde genommen sind OO DBs den relationalen Brüdern überlegen, aber dennoch konnten sie bis heute keinen Fuß fassen. Ausnahmen sind vielleicht einige wenige Nischen wie z.b. im embedded Bereich, wo Datenbanken wie db4o.de durchaus einen guten Weg darstellen. Auch Versant bedient im Grunde genommen nur eine Nische, da die meisten Firmen an Oracle & Co gebunden sind.

Welchen Vorteil bringt es dir als Programmierer auf JDO zu setzen? Simpel: Du kannst dahinter jederzeit beliebige Datenbanken hängen und somit effektiv diese in der Performance vergleichen. Zudem ist es in der Regel so, das die automatische SQL Generierung des JDO Mappers gut genug ist. Sicher wenn man ein einzelnes Statement handoptimiert wird der Mapper langsamer sein, aber in der Regel produziert dieser schnelleres SQL als man dies händisch ausformulieren könnte.

Zudem sind die meisten JDO Mappern einem direkten SQL Zugriff überlegen, da sie mehrere Level an Caches vorweisen können. Bis hin zu VM übergreifenden Distributed Caches ist alles denkbar.

Zur Frage des Urpsrungsposters: Kauf dir ein Datenbankenbuch das sich dem Them Performance widmet. Es wäre hier und jetzt ein wenig vermessen dir die Basics beibringen zu wollen.

Warum kann eine DB langsamer sein als sie sein könnte? Sind Indexe effizient gesetzt? Normalisierungsfehler? Muß man eventuell an einer bestimmten Stelle denormalisieren um der Performance genügen zu können? Sollte man vielleicht den Index auf eine andere physische Platte legen? Sollte man vielleicht anstelle des normalen Filesystems dem RDBMS ein Raw Device zuweisen, wodurch er sich den Umweg übers Filesystem ersparen kann? Wäre vielleicht ein Raid die Lösung zur Problembehebung? 

Oder sind wir gerade in die falsche Richtung gegangen? Ist vielleicht einfach nur deine Applikation der Flaschenengpass? Vielleicht irrst du dich ja und die DB stellt gar nicht den Engpass dar. Ja selbst dies wäre möglich.

MySQL ist im übrigen nicht wirklich eine schnelle DB. Ja sicher bei den Hobbyentwicklern ist es die schnellste / bestigste DB überhaupt, aber mal ehrlich, deren Anforderungen spiegeln nicht wirklich eine reale Applikation wieder. Sobald viele Relationen bestehen, multiple Threads transaktionssicherheit wollen und einfach die Anforderungen nach oben geschraubt werden. Ja ab da sind in der Regel ganz andere Datenbanken "schnell". Sogar die angeblich langsamere PostgreSQL kann hier recht schnell als Sieger hervorgehen.

Hol dir ein Buch das all diese Themen abdeckt und lern dich dort ein wenig ein. Eventuell lohnt es sich auch einen Consultant hinzuzuziehen der exakt nach deinen Randbedingungen Lösungen vorschlägt. (Bedenke, für den Preis einer VersantDB / Oracle kannst du schon einiges an Hardware upgraden, was eventuell also eine effizientere Lösung darstellt). 

Die meisten relevanten Bedingungen sind eben Applikationsspezifisch und somit können wir eigentlich nur generisch ins Blaue raten.

Im übrigen finde ich deinen Beitrag witzig.



> Ich möchte mich aber nicht durch die Verwendung von Nicht-Standardbefehlen auf FastObjects festlegen, sondern suche mehr eine Open Source Standart Objekt Datenbank, wie sie jetzt wohl vom Jakarta Projekt in der Entwicklung ist.



Cybis Interpretierung: Ich möchte nicht eine teure FastObjects sondern eine gratis Jakarta. Ich möchte nicht einen bezahlten Consultant bemühen, sondern hier gratis Lösungen erhalten;o) 

Warum denke ich so? JDO und somit Versant ist eher Standard als die meisten Implementierungen auf Jakarta. Jakarta Projekte hingegen sind frei / gratis aber nunmal in der Regel nicht Standard, denn Projekte wie Torque sind weit weg vom Standard. OJB wird JDO irgendwann mal wirklich supporten (angestrebt bei 2.0 wenn ich mich nicht irre). Etc. etc.

cybi


----------



## Sandra Haupt (5. August 2004)

Hallo Cybi,

vielen Dank für deine ausführlichen Erläuterungen. Du hast meinen zitierten Satz in der Tat richtig verstanden. Ich hatte hier auf eine effektive und kostengünstige Lösung gehofft, weil sich die von dir erwähnten Datenbanksysteme im fünfstelligen Bereich bewegen.

Nun habe ich mich drei Tage lang, 18 Stunden am Tag incl. Freizeit, mit den Dokumentationen der verschiedensten Datenbanken herumgeplagt. Zum Dank setzt mir mein Chef  heute die Pistole auf die Brust und möchte greifbare Resultate sehen. Er hat mir als "Leitender Programmierer" (ohne Java Kenntnisse) befohlen, die PostgreSQL Datenbank zu verwenden und für alle zu speichernden Klassen jeweils eine separate Tabelle anzulegen, also eine Objekt-Tabelle ohne Relationen. Damit wären dann alle Probleme gelöst.

Trotzdem Danke für eure Hilfe. 

Grüße, Sandra


----------



## squeaker (5. August 2004)

> _Original geschrieben von Valentin- _
> *Das mit der Overhead würde ich nicht unterschreiben halte ich für fraglich.
> Das war damals bei 1.1. so, aber seit der HotSpot VM und der relational GC
> ist das nicht mehr so der Fall.
> Ciao *



schön - stimmt aber trotzdem. Daher ist Java im numerischen Bereich noch vergleichsweise (zu Fortran z.B.) langsam, da es keine "leightweight" Objekte für numerische Klassen gibt (siehe dazu auch Ninja, link habe ich keinen, aber darüber musste ich mal Seminar halten) und ich weiss von einem Lehrstuhl bei uns der obiges Verfahren aus genau diesem Grund implementiert hat.

Es ist einfach so - gc kostet Zeit (und wird immer), Speicher vom OS anfordern und releasen kostet Zeit und diesen mit den Objekt-Headern zu füllen kostet auch Zeit. Daher ist es vielleicht besser geworden - aber gut ist es sicher noch nicht.


----------



## Cybernd (5. August 2004)

Zum Thema GC: Schmarrn hoch 3

GC spart Zeit. Denn er kann den Speicher effizienter verwalten als es mit manueller Speicherfreigabe möglich wäre. 

Dennoch ist Java wegen des Speichers langsamer. Dies liegt aber nicht am GC, sondern daran das einfach von Haus aus für kleinstObjekte mehr Speicher benötigt wird. Und Speicher sinnvoll zu beschreiben kostet nunmal Zeit.

Nur eben die Aufräumzeit selbst ist schneller als du es z.b. mit dem c++ free erreichen könntest. Ja ich weiß dies wirst du mir jetzt nicht glauben.

---

Zum Thema DB:
Kauf dir ein Buch zum Thema JDO. Ja ich weiß, die Teile kosten gleich mal 40 Euro ;o) 

Argumentation für den Chef: Freiheit
Du kannst bei Bedarf einen höherwertigeren Mapper verwenden. Zu Beginn verwendest du jpox.org oder jcredo, die eine brauchbare freie Version anbieten. Im Falle eines Engpasses kannst du Caches dazustecken oder Produkte anderer Hersteller verwenden. Der Migrationsaufwand wird hierbei so gering wie möglich bleiben. Versuch gar nicht erst dir das ohne Fachliteratur beizubringen, denn du wirst dir damit keinen Gefallen tun.

Zum Thema Tabellenstruktur: Ja üblicherweise verwendet so ein Mapper exakt eine Tabelle pro Objekt. Selbst bei einer 1:1 Verbindung mapped man auf 2 Tabellen. Dennoch die daraus resultierenden Joins kosten üblicherweise Performance, wodurch manchmal hier denormalisiert wird.

JDO bietet dir zudem das Argument gegebenfalls später ohne Änderung des Codes auf eine ObjektDB umsteigen zu können. Du kannst aber auch einfach z.b. einige Namespaces aus der Maschine 1 beziehen, die restlichen Objekte wiederum von der Maschine 2. Derartige Änderungen beeinflußen nicht die Applikationslogik, wodurch sie später im lebenden System beim Auftreten des Engpasses relativ leicht vorzunehmen sind. 

Ansonsten wenn du dich gegen JDO & Co entscheidest solltest du dir zumindestens das DAO Designpattern antun. Hierzu verweise ich zu http://java.sun.com/blueprints/patterns/DAO.html

Abschließend noch ein kleiner Link ins eigene Forum:
http://board.aenaeis.org/index.php?showtopic=220

Für meinen Zweck ergab sich JPox als geeignetste Implementierung. Bei dir würde ich vielleicht eher Richtung Jcredo schielen. 

Alternativ zu JDO gäbe es noch den pragmatischen Weg => hibernate. Hierbei hast du aber das Problem das du kein Interface hast, das dir den Wechsel der Implementierung ermöglichen würde. Dafür ist das Tool an sich bereits reifer als die momentan vorhandenen JDO Implementierungen wie z.b. jpox. Dennoch strategisch gesehen halte ich hibernate für das falsche Pferd. JDO geht in Richtung lightwight Peristierung wärend Hibernate jetzt von JBoss aufgekauft wurde und somit bewußt Richtung EJB 3 getrieben wird.

cybi


----------



## Thomas Darimont (5. August 2004)

Hallo!



> Nur eben die Aufräumzeit selbst ist schneller als du es z.b. mit dem c++ free erreichen könntest.



Unter C++ heißen die Befehle zum Speichermanagement 
new und delete

in C heißen diese
malloc und free 

Nur mal so am Rande.

Gruß Tom


----------



## Cybernd (5. August 2004)

War Sinnbildlich gemeint ;P Ich wollte nicht darüber nachdenken, wie die Befehle wirklich heißen.

cybi


----------



## squeaker (9. August 2004)

> _Original geschrieben von Cybernd _
> *Z
> Nur eben die Aufräumzeit selbst ist schneller als du es z.b. mit dem c++ free erreichen könntest. Ja ich weiß dies wirst du mir jetzt nicht glauben.
> *



ich würde in C/C++ das ganze ja ähnlich gestalten und nicht immer mit new und delete neuen Speicher anfordern und freigeben. Alles andere wäre schmarrn (bei vielen Objekten). Ich glaube dir das sofort mit dem gc und schneller als free - schliesslich scheinst du ja da mehr Ahnung zu haben als ich. Aber ein schlechtes Design kann auch von einem guten Compiler nicht  wett gemacht werden. Daher - erst  gutes Design. Und das bedeutet bei vielen kleinen Objekten eben ein eigenes Verwaltungsobjekt um das ständige allozieren/deallozieren von Speicher zu vermeiden.


----------

