JPA- Entities bleiben nach dem Löschen (unsichtbar?) in der Datenbank

Pvt. Ota

Neues Mitglied
Hallo,

ich habe folgende JPA-Entity:

Java:
@Entity
public class Test implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Lob
    public byte[] data;

}

Nun speichere ich davon z.B. 100 Einträge in der Datenbank, wobei jeder Eintrag 3 MB groß ist. Wenn ich jetzt eine Abfrage auf die Datenbank mache
Code:
(SELECT x FROM Test x)
, werden wie erwartet 100 Einträge angezeigt und die Datenbank belegt ca. 300 MB im Dateisystem.

Jetzt lösche ich alle Einträge wieder aus der Datenbank, indem ich für jeden Eintrag
Code:
entityManager.remove(test)
aufrufe.
Die gleiche SQL-Abfrage liefert nun zurück, dass die Tabelle leer ist. Die Datenbank belegt jedoch immer noch 300 MB im Dateisystem! Was läuft hier falsch? Wenn ich wieder 100 neue hinzufüge wächst die Datenbank sogar auf 600 MB und so weiter...
Erst durch ein DROP der Tabelle wird der Speicherplatz wieder freigegeben.

Ausprobiert hab ich das mit der JavaDB und Oracle XE, jeweils mit EclipseLink.

Vielen Dank für die Antworten!
 
Ich gehe mal davon aus, dass alle Transaktionen abgeschlossen sind und die Daten per SQL wirklich nicht mehr zu holen sind.

Wenn das DMBS der Meinung ist, den Speicherplatz vorhalten zu müssen, dann ist das dessen (unter Umständen gut begründete) Entscheidung. Ein Programm, welches plötzlich weniger Arbeitsspeicher benötigt, verringert auch nicht automatisch seinen Speicherverbrauch. Plattenoperationen sind performancetechnisch nochmal um einiges teurer. Wenn es wirklich wichtig ist, dass der Speicherplatz sofort freigegeben wird, würde ich mir mal die Dokumentation der jeweiligen Datenbank ansehen. In der Regel sind die ja sehr stark konfigurierbar. Das hat dann wenig mit Java zu tun.
 
bei einem remove werden die Objekte für das löschen in der DB "vorgemerkt".
In deiner Application sind die dann zwar weg aber nicht in der DB

mit einem entityManager.flush() wird es, wenn ich mich recht erinnere, mit der Datenbank synchronisiert.
 
Danke für die Antworten!
Ich gehe mal davon aus, dass alle Transaktionen abgeschlossen sind und die Daten per SQL wirklich nicht mehr zu holen sind.
Ja, das ist der Fall.

Hm, aber sollte er den Speicherplatz dann nicht irgendwann mal freigeben, wenn ich immer wieder lösche, hinzufüge, lösche, ...? Die Datenbank macht bei mir den Eindruck, als wolle sie ins Unendliche wachsen... Oder muss ich mich dann wirklich immer selber darum kümmern, dass der Speicherplatz freigegeben wird?

@parabool: Ein flush() hab ich auch schon hinter das remove() gesetzt. Das ändert aber leider auch nichts.
 
Hm, aber sollte er den Speicherplatz dann nicht irgendwann mal freigeben, wenn ich immer wieder lösche, hinzufüge, lösche, ...? Die Datenbank macht bei mir den Eindruck, als wolle sie ins Unendliche wachsen... Oder muss ich mich dann wirklich immer selber darum kümmern, dass der Speicherplatz freigegeben wird?

Ich würde mich nicht drum kümmern, wenn es keine Probleme bereitet. Klar kann es auf beschränkten Geräten (Buzzword Embedded Systems) vorkommen, dass der Speicher zu schnell knapp wird. Dann muss man sich auf jeden Fall Gedanken darum machen. In allen anderen Fällen sollte der Speicher natürlich irgendwann freigegeben werden oder zumindest nicht mehr wachsen.

Wie gesagt: Das wird dann sehr datenbankspezifisch. Datenbanken werden mit irgendeiner Standardkonfiguration ausgeliefert und müssen bei Bedarf stark an die eigenen Bedürfnisse angepasst werden (aus meinen Erfahrungen: MySQL bietet verschiedene Profile, PostgreSQL ist zu Beginn sehr konservativ). DB Tuning ist ein großes Gebiet.

Vielleicht bietet das spezielle DBMS ja auch eine Funktion an, mit der ein Aufräumen des Speichers angestoßen werden kann. Bei PostgreSQL gibt es z. B. [c]VACUUM[/c].
 
Zuletzt bearbeitet:
Kein Filesystem macht Dateien kleiner...
Beim Schreiben hast Du den Tablespace vergrößert, die Daten müssen schliesslich irgendwo stehen.
Beim Anlegen war dein Tablespace vielleicht 10 Kb gross -> Definition und leerer Index
Dann hast Du Daten reingeschrieben -> 300 Kb -> Definition, gefüllter Index, Daten
Dann hast Du gelöscht -> die DB markiert die Daten "zum Überschreiben" und leert den Index, physikalische(!) Dateigröße bleibt
Wenn Du jetzt wieder Daten schreibst, kann es sein, dass dein Tablespace NICHT grösser wird (je nach Strategie der DB)
Wenn Deine Datenbank eine "Shrink" oder "Reorg" Methode kennt, DANN wird ein neuer Tablespace mit den aktuell vorhandenen Daten "kopiert", der ist dann kleiner.
Dieses "Shrink" oder "Reorg" oder so musst Du vom Administrationswerkzeug der DB aus aufrufen, die DB ist solange offline!
 

Zurück
Oben