it-swarm.com.de

Wie kann ich Speicherplatz in PostgreSQL zurückfordern?

Ich habe eine lokale Installation der 9.1-Datenbank mit wenigen Tabellen, die cca hatten. 300 Millionen Datensätze und die Datenbank wuchs auf etwa 20 GB. Danach gab ich delete from Befehl, um alle Datensätze daraus zu löschen (ich hätte truncate verwenden sollen, aber das wusste ich nicht). Also habe ich meine Datenbank vollständig abgesaugt, um Speicherplatz zurückzugewinnen, aber es hilft einfach nicht. Mein Problem sieht identisch aus mit dieses , aber es gibt keine Lösung. Ich habe bereits diesen Thread und die Dokumentation zu "Wiederherstellen des Speicherplatzes" überprüft, kann aber immer noch keine Lösung finden. Ich benutze diesen Code, um die Größe aller Tabellen zu ermitteln

 SELECT nspname || '.' || relname AS "relation",
 pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
 FROM pg_class C
 LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
 WHERE nspname NOT IN ('pg_catalog', 'information_schema')
 AND C.relkind <> 'i'
 AND nspname !~ '^pg_toast'
 ORDER BY pg_total_relation_size(C.oid) DESC
 LIMIT 15;

Insgesamt jedoch weniger als 1 GB

SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database 

zeigt immer noch etwa 20 GB. Jeder Rat sehr geschätzt.

26
arcull

Obwohl Sie es nicht angegeben haben, gehe ich aus Ihren Verweisen auf Dokumente, denen Sie gefolgt sind, davon aus, dass Sie ein VACUUM FULL für die Datenbank und/oder die betroffenen Tabellen durchgeführt haben. Sie haben auch nicht angegeben, welche Postgresql-Version Sie verwenden - ich gehe davon aus, dass sie> 9.0 ist (VACUUM FULL hat sich zuvor anders verhalten).

VACUUM FULL schreibt betroffene Tabellen in neue Dateien um und löscht dann die alten Dateien. Wenn jedoch in einem Prozess die alte Datei noch geöffnet ist, löscht das Betriebssystem die Datei erst dann, wenn der letzte Prozess sie geschlossen hat.

Wenn dies praktisch ist, würde ein Neustart der Datenbank sicherstellen, dass alle geöffneten Dateien geschlossen werden.

Wenn dies nicht praktikabel ist, können Sie möglicherweise überprüfen, ob dies Ihr Problem ist, und herausfinden, in welchem ​​Prozess die Dateien geöffnet sind.

Wenn Sie Linux (oder die meisten anderen Unix-ähnlichen Systeme) verwenden, können Sie den Befehl 'lsof' verwenden, um eine Liste aller Dateien zu erhalten, die in allen Prozessen geöffnet sind. Dateien, die geöffnet sind, aber inzwischen gelöscht wurden, werden an den Dateinamen '(gelöscht)' angehängt. Sie können also die Ausgabe von lsof durchsuchen und nach gelöschten Dateien suchen, wie folgt:

Sudo lsof -u postgres | grep 'deleted'

Wenn dadurch Prozesse identifiziert werden, bei denen die alten Dateien noch geöffnet sind, können Sie diesen Prozess mit pg_terminate_backend beenden:

SELECT pg_terminate_backend(xxx);

dabei ist xxx die PID des Prozesses, die in der lsof-Ausgabe gefunden wird.

Bei Verwendung von Windows kann dasselbe Prinzip gelten, da postgres Dateien mit dem Flag FILE_SHARE_DELETE öffnet, wodurch Dateien gelöscht werden können, die in einem anderen Prozess geöffnet sind. Der Befehl ' handle ' ist das grobe Äquivalent von lsof, obwohl ich nicht sicher bin, ob Sie feststellen können, ob die Dateien gelöscht wurden oder nicht, sodass möglicherweise zusätzliche Arbeiten erforderlich sind.

Es ist eine andere Frage, warum solche Prozesse an alten Dateihandles hängen bleiben würden. In dem Thread , den Sie in Ihrer Frage zitiert haben, scheint Tom Lane jedoch zu implizieren, dass dies passieren kann.

23
harmic