Juni 19th, 2007

...now browsing by day

 

Opposition - Die wohl wichtigste Waffe der Demokratie

Dienstag, Juni 19th, 2007

Auf die Bitte der Linksfraktion, die Benutzung deutscher Pässe bei Terroranschlägen oder Anschlagsplanungen tabelliert nach Jahr und Anlass darzustellen, lautet die lakonische Antwort: “Der Bundesregierung sind keine derartigen Fälle bekannt.” Damit ist die Argumentationskette brüchig geworden, die die Aufnahme biometrischer Informationen als sinnvolle Maßnahme im Kampf gegen den Terror begründet.

Quelle: Bundesregierung: Terroristen nutzten keine deutschen Pässe

Manchmal finde ich einfach nur gut, dass wir in der Demokratie auch mal von aufmerksamen Oppositionen profitieren können. Eigentlich ist nur schade, dass solche Informationen es nie in die Tagesschau schaffen…

Hibernate - Performanceschub dank Sessionflush und evict

Dienstag, Juni 19th, 2007

Wir hatten auf Arbeit einige Performanceprobleme bei unseren Jobs, da diese beim durchgehen der Datenmengen zunehmen langsamer wurden.
Nach dem uns ein Freelancer [1] den Tipp gab, dass alle geholten Objekte auch nach dem Abarbeiten noch in der Spring-Session existent sind, war schnell klar, dass dies das Grundproblem war.

Geholte Objekte werden dank Lazy Load[2] nicht komplett aus der Datenbank geholt, sondern nur die benötigten Teile. So kann man zum Beispiel verhindern, dass anhängige Objekte nur bei Bedarf geladen werden und die Datenmenge daher überschaubar bleibt.
Diese Objekte werden bearbeitet und dann wieder gespeichert und verbleiben in der Session. Sie werden nicht sofort in die Datenbank geschrieben, da die Datenbankkommunikation in Transaktionen und damit gebündelt erfolgen soll.

Wenn nun in einem Job viele Daten verarbeitet werden, wird die Session immer voller und damit langsamer. Der Job wird also mit zunehmender Dauer langsamer.

Damit die Session nicht überfüllt wird, wurde uns evict()[3] vorgeschlagen. Evict löscht ein Object aus der Session.

Wie wir nun feststellen mussten, ist dies aber auch problematisch, da ja wie oben beschrieben die geänderten Objekte nicht unbedingt sofort geschrieben werden. Wir brauchten also noch einen Trigger, damit dies geschieht. Zum Glück bietet Spring das ebenfalls gleich an. Hier kommt der allseits bekannte Befehl flush()[4] ins Spiel. An der richtigen Stelle und danach ein evict() und alle sind glücklich :)

*UPDATE*
Ich zitiere einmal die Mail eines Kollegen, der brachte alles nochmal auf den Punkt inklusive guter Lösung:

Wichtige Hibernate-Infos:

*Problem:*
Im Zuge der Hibernate-Performanceoptimierungen wurde an verschiedenen Stellen ein “evict” eingebaut. Das hat zu Problemen geführt, Datenänderungen wurden nicht gespeichert.

*Erklärung*
Bei einem evict wird das Objekt sofort aus der Hibernate Session entfernt, es findet kein Dirty-Checking mehr statt und Änderungen an dem Objekt werden somit nicht mehr in die Datenbank zurückgeschrieben. Das ist ein Problem, weil der Aufruf von Service.update nicht sofort die Änderungen in die Datenbank schreibt, sondern das erst beim Session.flush passiert, bei dem dann Hibernate ein Dirty-Checking der gerade in der Session befindlichen Entities durchführt. Das Session.flush passiert entweder beim Committen einer Transaktion, beim Schliessen der Session oder bevor ein Query ausgeführt wird.

*Lösung:*
In den Services gibt es jetzt neben der evict/evictAll die neuen Methoden flushAndEvict/flushAndEvictAll. Diese führen vor dem evict ein Session.flush aus und stellen damit sicher, dass alle geänderten Entities auch mit der Datenbank synchronisiert werden. Diese Methoden sind zu Verwenden, wenn Entities geändert wurden, die dann evicted werden sollen. Wenn es nur um unveränderte Entities geht (bspw. beim Lesen), kann wie bisher das alte evict genutzt werden. Auch bei einem create reicht das normale evict, weil das Insert immer sofort ausgeführt wird.

Natürlich ist es sinnvoll, flushAndEvictAll zu benutzen mit einem Batch von Objekten, so dass immer mehrere Objekte zusammen aktualisiert werden.

Wenn es nur darum geht, durch eine Liste von Entities zu gehen, diese zu lesen und danach zu evicten, dann geht das am einfachsten mit dem Auto-Evict des HibernateResults (das HibernateResult ist unsere Lazy-Loading Implementierung der Liste, die von resultsByCriteria zurückgegeben wird):

final List <customer> customers = getCustomers();
HibernateResult.activateAutoEvict(customers);
for (Customer customer : customers) {
// do something with customer entitiy
}
HibernateResult.close(customers);

In dieser Schleife werden die einzelnen Customer-Instanzen erst bei Bedarf geladen und dann sofort evicted, wenn der naechste Customer geladen wird.

[1] Payman Jorand-Lippe
[2] Lazy Load
[3] evict()
[4] flush()

Stoppt die Vorratsdatenspeicherung! Jetzt klicken & handeln!Willst du auch bei der Aktion teilnehmen? Hier findest du alle relevanten Infos und Materialien: