← Datenbankadministration für Sysadmins
Speicherwachstum und Routinewartung: Aufblähung, Aufräumen und der Preis des Platzes
200 Millionen Zeilen gelöscht, Vorgang fehlerfrei — und das Volume ist genauso voll wie vorher. Das ist keine Störung, sondern die dokumentierte Arbeitsweise: Alte Zeilenversionen dürfen nicht verschwinden, solange jemand sie noch sehen könnte. Dieses Modul trennt Aufblähung von echtem Wachstum, zeigt warum die Maßnahme gegen volle Platten selbst zusätzlichen Platz braucht — und behandelt die Uhr, die im Hintergrund läuft und deren Ablauf die Dokumentation als katastrophalen Datenverlust bezeichnet.
Lehrtext · 11 Abschnitte · zuletzt geprüft: 2026-09-12
Warum Löschen keinen Platz freigibt
Ein Ticket, das jeder Datenbankbetrieb kennt: Es wurden 200 Millionen alte Zeilen gelöscht, der Vorgang lief erfolgreich durch — und das Volume ist genauso voll wie vorher. Das ist kein Fehler, sondern die dokumentierte Arbeitsweise.
UPDATE oder ein DELETE einer Zeile die alte Version der Zeile nicht sofort. Dieser Ansatz ist nötig, um die Vorteile der Mehrversionen-Nebenläufigkeitssteuerung zu erhalten: Die Zeilenversion darf nicht gelöscht werden, solange sie für andere Transaktionen möglicherweise noch sichtbar ist.Das ist dieselbe Mechanik, die im Modul über Transaktionen die Isolationsstufen trägt: Wenn eine laufende Abfrage einen Schnappschuss von vorhin sieht, muss dieser Schnappschuss irgendwo stehen. Er steht in den alten Zeilenversionen. Sie wegzuwerfen, solange jemand sie noch sehen könnte, würde die Garantie brechen.
Tote Zeilenversion — Eine überholte oder gelöschte Zeilenversion, für die sich keine laufende Transaktion mehr interessiert. Sie belegt Platz, bis eine Aufräumung ihn zur Wiederverwendung freigibt.
Aufblähung — Der Anteil einer Tabelle, der aus toten Zeilenversionen besteht. Er wächst mit der Änderungsrate und schrumpft nur durch Aufräumen.
Bei SQL Server ist die Mechanik anders, das Ergebnis vergleichbar: Auch dort gibt eine gelöschte Zeile ihren Platz nicht an das Betriebssystem zurück, sondern hinterlässt freien Raum innerhalb der Datendatei, der für neue Zeilen wiederverwendet wird.
Was das Aufräumen tut — und was nicht
Der Befehl dafür heißt in PostgreSQL VACUUM, und seine wichtigste Eigenschaft ist eine Einschränkung, die regelmäßig übersehen wird.
VACUUM entfernt tote Zeilenversionen in Tabellen und Indizes und markiert den Platz als für künftige Wiederverwendung verfügbar. Sie gibt den Platz jedoch nicht an das Betriebssystem zurück — außer in dem Sonderfall, dass eine oder mehrere Seiten am Ende der Tabelle vollständig frei werden und sich eine exklusive Tabellensperre leicht erlangen lässt.Nach einem erfolgreichen Aufräumen ist die Tabelle also genauso groß wie vorher — aber innen hohl. Der nächste Schwung neuer Zeilen passt hinein, ohne dass die Datei wächst. Genau das ist der Zweck.
Die Dokumentation formuliert das Ziel ausdrücklich anders, als die meisten es erwarten: Es geht nicht darum, Tabellen auf ihrer Mindestgröße zu halten, sondern einen stationären Zustand des Platzverbrauchs zu erreichen — jede Tabelle belegt ihre Mindestgröße plus so viel, wie zwischen zwei Aufräumläufen verbraucht wird.
SELECT, INSERT, UPDATE und DELETE funktionieren laut Dokumentation normal weiter; lediglich die Definition der Tabelle lässt sich währenddessen nicht ändern. Der Preis ist E/A-Last, die andere Sitzungen spüren können — dafür gibt es eigene Drosselungsparameter.Der Ausweg, der mehr Platz braucht als vorhanden ist
Wenn die Aufblähung schon groß ist, reicht die Standardform nicht mehr, um die Datei zu verkleinern. Dafür gibt es VACUUM FULL — und der hat zwei Eigenschaften, die ihn im Ernstfall oft ausschließen.
- Sperre
- Verlangt laut Dokumentation eine
ACCESS EXCLUSIVE-Sperre auf der Tabelle und kann deshalb nicht parallel zu anderer Nutzung laufen. Die Tabelle ist währenddessen vollständig unerreichbar. - Platzbedarf
- Schreibt eine vollständig neue Fassung der Tabellendatei ohne toten Raum. Dafür braucht er zusätzlichen Plattenplatz etwa in der Größe der Tabelle, bis der Vorgang abgeschlossen ist.
- Dauer
- Läuft laut Dokumentation deutlich langsamer als die Standardform.
VACUUM FULL fast immer, weil die Platte voll ist. Genau dann steht der zusätzliche Platz in Größe der Tabelle nicht zur Verfügung. Das gilt gleichermaßen für die verwandten Wege über CLUSTER und die tabellenneuschreibenden Formen von ALTER TABLE: Alle verlangen dieselbe Sperre, und alle brauchen vorübergehend den doppelten Platz, weil die alten Kopien von Tabelle und Indizes erst freigegeben werden können, wenn die neuen fertig sind.Die Dokumentation zieht daraus eine klare Empfehlung: Administratoren sollten anstreben, die Standardform zu verwenden und VACUUM FULL zu vermeiden. Mäßig häufige Standardläufe sind der bessere Weg als seltene vollständige — und eine Tabelle auf Mindestgröße zu schrumpfen bringt ohnehin wenig, wenn sie gleich wieder wächst.
Autovacuum: was er tut und was er nie tut
Beide Systeme räumen im Hintergrund selbsttätig auf. In PostgreSQL heißt der Vorgang Autovacuum-Daemon, und er hat eine Eigenschaft, die man kennen muss, bevor man ihm ein Problem zuschreibt.
VACUUM FULL ausführen. Wer darauf wartet, dass die Datei durch ihn kleiner wird, wartet vergeblich — nicht weil er nicht funktioniert, sondern weil das nicht seine Aufgabe ist.Sein Vorteil gegenüber einem festen Zeitplan liegt in der Dynamik. Die Dokumentation benennt die Schwäche des Zeitplans genau: Hat eine Tabelle einen unerwarteten Ausschlag an Änderungsaktivität, kann sie so stark aufblähen, dass ein VACUUM FULL wirklich nötig wird. Der Daemon plant dagegen anhand der tatsächlichen Aktivität. Ihn vollständig abzuschalten nennt die Dokumentation unklug, sofern die Last nicht außergewöhnlich vorhersagbar ist.
Er übernimmt dabei eine zweite Aufgabe, die im Modul über Ausführungspläne schon aufgetaucht ist: Er stößt auch ANALYZE an, sobald sich der Inhalt einer Tabelle hinreichend geändert hat. Die Dokumentation nennt die Grenze dieses Automatismus gleich mit — er plant ausschließlich anhand der Zahl eingefügter oder geänderter Zeilen und hat keine Kenntnis davon, ob daraus überhaupt eine bedeutsame statistische Änderung folgt.
Aufräumen macht auch Abfragen schneller
Die Wirkung des Aufräumens auf den Plattenplatz ist die bekannte. Es gibt eine zweite, die weniger bekannt ist und unmittelbar auf die Abfrageleistung durchschlägt.
Beim Aufräumen wird laut Dokumentation je Tabelle eine Sichtbarkeitskarte gepflegt. Sie vermerkt, welche Seiten ausschließlich Zeilen enthalten, die für alle laufenden — und alle künftigen — Transaktionen sichtbar sind, bis die Seite wieder geändert wird. Das hat zwei Zwecke.
- Der nächste Aufräumlauf wird kürzer. Er kann solche Seiten überspringen, weil es dort nichts zu tun gibt. Aufräumen macht das nächste Aufräumen billiger — und umgekehrt wird ein lange vernachlässigter Lauf überproportional teuer.
- Manche Abfragen kommen ohne die Tabelle aus. Indizes tragen keine Sichtbarkeitsinformation, weshalb ein gewöhnlicher Indexzugriff zu jedem Treffer zusätzlich die Tabellenzeile holen muss, um zu prüfen, ob sie für die aktuelle Transaktion überhaupt sichtbar ist. Steht in der Sichtbarkeitskarte, dass auf einer Seite alles sichtbar ist, entfällt dieser Griff — die Abfrage wird allein aus dem Index beantwortet.
Damit schließt sich der Kreis zum Modul über Ausführungspläne: Wer dort eine plötzlich langsamere Abfrage untersucht und in Plan und Index nichts findet, sollte prüfen, wann die Tabelle zuletzt aufgeräumt wurde. Die Ursache liegt dann nicht im Zugriffsweg, sondern in der Wartung.
Die Uhr, die niemand sieht
Es gibt einen Grund fürs Aufräumen, der nichts mit Plattenplatz zu tun hat und weit schwerer wiegt. Er ist der Grund, warum Aufräumen auch auf einer Tabelle nötig ist, die nur gelesen wird.
Die Sichtbarkeitsregeln beruhen auf dem Vergleich von Transaktionskennungen: Eine Zeilenversion mit einer höheren Einfüge-Kennung als die der aktuellen Transaktion liegt „in der Zukunft“ und soll nicht sichtbar sein. Diese Kennungen sind aber laut Dokumentation 32 Bit groß. Ein Cluster, der lange genug läuft — mehr als vier Milliarden Transaktionen — würde einen Überlauf erleiden: Der Zähler springt auf null, und plötzlich erscheinen Transaktionen, die in der Vergangenheit lagen, als in der Zukunft liegend.
Verhindert wird das durch das Einfrieren: Das Aufräumen markiert Zeilen als eingefroren, was bedeutet, dass sie von einer Transaktion eingefügt wurden, die weit genug in der Vergangenheit bestätigt hat. Eingefrorene Zeilenversionen gelten für alle normalen Transaktionen als „in der Vergangenheit“, unabhängig vom Überlauf — und bleiben damit gültig, solange sie existieren.
SQL Server: Verkleinern ist keine Wartung
Auf der SQL-Server-Seite heißt die Operation, die Platz an das Betriebssystem zurückgibt, Verkleinern. Sie ist der direkte Gegenpart zu VACUUM FULL — und die Dokumentation ist in ihrer Bewertung ungewöhnlich deutlich.
Technisch arbeitet sie so: Datenseiten werden vom Ende der Datei in unbelegten Raum weiter vorne verschoben. Entsteht am Ende genügend freier Platz, können die dortigen Seiten freigegeben und an das Dateisystem zurückgegeben werden.
Dazu kommen zwei Grenzen, die überraschen. Eine Datenbank lässt sich nicht unter ihre Mindestgröße verkleinern — das ist die bei der Erstellung angegebene oder die zuletzt ausdrücklich gesetzte Größe. Eine Datenbank, die mit 10 MB erzeugt wurde und auf 100 MB gewachsen ist, lässt sich auf 10 MB verkleinern, selbst wenn alle Daten gelöscht wurden, aber nicht darunter. Und: Während eine Sicherung läuft, lässt sich nicht verkleinern — und umgekehrt.
Abkürzungen mit Preis
Es gibt zwei Wege, die Aufräumarbeit gar nicht erst entstehen zu lassen. Beide sind richtig, und beide haben einen benannten Nachteil.
TRUNCATEstattDELETE- Wird der gesamte Inhalt einer Tabelle regelmäßig geleert, entfernt
TRUNCATEihn laut Dokumentation sofort, ohne dass anschließend aufgeräumt werden müsste, um den Platz zurückzugewinnen. Nachteil: Die strengen Nebenläufigkeits-Semantiken werden dabei verletzt. - Partitionieren statt Löschen
- Alte Daten liegen in einer eigenen Partition, die als Ganzes entfernt wird. Nachteil: Der Entwurf muss von Anfang an passen, und die Statistikpflege der Elterntabelle fällt aus der Automatik heraus.
Beiden gemeinsam ist der eigentliche Lehrsatz dieses Moduls: Platz zurückzugeben ist in beiden Systemen teuer und störend. Der billige Weg besteht darin, ihn gar nicht erst in großer Menge entstehen zu lassen — durch häufiges, leichtes Aufräumen statt seltener, schwerer Eingriffe.
Das Wartungsfenster ordnen
Ein nächtliches Fenster enthält meist mehrere Arbeiten, und ihre Reihenfolge ist nicht beliebig — jede erzeugt Voraussetzungen für die nächste oder macht deren Ergebnis zunichte.
Vier Arbeiten, eine Reihenfolge
Szenario
Im Fenster stehen an: eine Vollsicherung, ein Aufräumlauf, das Auffrischen der Planerstatistiken und ein Neuaufbau stark fragmentierter Indizes.
Anforderungen
- Begrenztes Fenster
- Die Datenbank ist währenddessen nicht in Nutzung
- Alle vier Arbeiten sollen wirksam sein, nicht nur ausgeführt
Schritte
- Aufräumen zuerst: Es entfernt tote Zeilenversionen und ist die Voraussetzung dafür, dass die folgenden Schritte nicht auf Ballast arbeiten.
- Indexpflege danach: Sie schreibt Indexstrukturen neu. Vorher aufzuräumen verhindert, dass tote Einträge mit übernommen werden.
- Statistiken danach: Sie sollen den Zustand nach allen Strukturänderungen abbilden. Frischt man sie vorher auf, beschreiben sie einen Stand, den es am Morgen nicht mehr gibt.
- Sicherung zuletzt: Sie soll den fertigen, aufgeräumten Stand einfangen. Eine Sicherung vor der Wartung sichert den Zustand, den man gerade loswerden wollte — bei SQL Server kollidiert sie zudem mit einer Verkleinerung, weil beides nicht gleichzeitig laufen darf.
Merksatz: Die Reihenfolge folgt der Abhängigkeit, nicht der Gewohnheit: Was Zustand verändert, kommt vor dem, was Zustand beschreibt oder konserviert.
FULL — erhebliches Protokollaufkommen. Ein Indexneuaufbau kann die Protokolldatei stärker wachsen lassen als ein ganzer Geschäftstag. Wer das Fenster plant, plant deshalb auch den Platz, den die Wartung selbst verbraucht.Beobachten statt reagieren
Wachstum ist der eine Fall, in dem sich ein Vorfall zuverlässig vorher ankündigt — vorausgesetzt, jemand sieht hin. Drei Größen reichen dafür weitgehend aus.
- Der Anteil toter Zeilenversionen je Tabelle. Er zeigt, ob das Aufräumen hinterherkommt. Steigt er über Wochen, ist die Ursache die Aufräumrate, nicht die Datenmenge.
- Der Zeitpunkt des letzten Aufräumens und Analysierens je Tabelle. Beide Systeme führen ihn mit. Eine große Tabelle, die seit Monaten nicht angefasst wurde, ist der Kandidat für beide Probleme dieses Moduls — Aufblähung und die Uhr der Transaktionskennungen.
- Der freie Platz im Volume gegen den Zuwachs je Woche. Erst diese beiden zusammen ergeben eine Vorwarnzeit. Ein Füllstand allein ergibt sie nicht.
log_autovacuum_min_duration protokolliert Aufräumvorgänge ab einer angegebenen Dauer; die Voreinstellung liegt bei zehn Minuten. Wichtiger als die Dauer ist ein Nebeneffekt, den die Dokumentation ausdrücklich nennt: Sobald der Wert nicht auf „aus“ steht, wird auch dann eine Meldung geschrieben, wenn ein Aufräumvorgang wegen einer konfliktierenden Sperre oder einer nebenläufig entfernten Relation übersprungen wurde. Genau diese übersprungenen Läufe sind die Ursache, wenn eine einzelne Tabelle jahrelang aufbläht, während alle anderen sauber bleiben.Die Reihenfolge, die das zusammenhält
Schritt drei entscheidet über alles Weitere. Echtes Datenwachstum löst man mit Kapazität oder mit Archivierung. Aufblähung löst man mit Aufräumen — und wer sie für Wachstum hält, kauft Platten gegen ein Problem, das keine Platten braucht.
Jetzt anwenden
Diesen Stoff gibt es als Modul mit bewerteten Entscheidungs-Checks — dieselbe Einführung, danach die Übungen.
Zum Modul →Quellen & Aktualität6 Primärquellen · zuletzt geprüft:
- 01postgresql.org/docs/current/routine-vacuuming.html
- 02postgresql.org/docs/current/storage-file-layout.html
- 03postgresql.org/docs/current/monitoring-stats.html
- 04postgresql.org/docs/current/runtime-config-logging.html
- 05learn.microsoft.com/en-us/sql/relational-datab…es/shrink-a-database
- 06learn.microsoft.com/en-us/sql/relational-datab…ry-models-sql-server