Ich versuche, den gesamten Inhalt einer großen Tabelle über die Befehlszeile mit zu sichern pqsl, stoße jedoch auf ein Problem, bei dem die Speichernutzung bis zu dem Punkt steigt, an dem der Prozess beendet wird, bevor überhaupt Daten ausgegeben werden.
Was ich nicht verstehe, ist: Warum gibt die Abfrage nicht sofort Ergebnisse zurück und wird abgeschlossen, ohne dass der Speicher knapp wird?
Hier ist eine Erklärung genau dessen, was ich versuche:
Ich habe einen Tisch, sag:
CREATE TABLE big
(
id integer,
rand double precision
)
Eine große Anzahl von Zeilen wird eingefügt (50 Millionen):
insert into big
select generate_series(1, 50000000) AS id, random();
Der Abfrageplan zum Auswählen jeder Zeile sieht wie folgt aus (nicht überraschend):
$ psql -d big -c "explain select * from big;"
QUERY PLAN
----------------------------------------------------------------
Seq Scan on big (cost=0.00..924326.24 rows=50000124 width=12)
(1 row)
Ich versuche dann, den Inhalt in eine Datei zu kopieren:
$ psql -d big -c "select * from big;" > big.dump
Wie ich oben sagte, schlägt dieser Befehl fehl, bevor Daten geschrieben werden, anscheinend indem immer mehr Speicher belegt wird, bevor er vom Betriebssystem getötet wird (von "OOM Killer").
Hinweis: Ich verstehe, dass ich damit pg_dumpetwas Ähnliches erreichen könnte, aber in Wirklichkeit ist meine Abfrage komplexer als diese - insbesondere möchte ich jede Zeile beim Dumping als JSON codieren .
Einige Konfigurationsdetails:
- postgresql version = 9.3.4
- work_mem = 1 MB
- shared_buffers = 128 MB
- effektive_cache_size = 128MB
psqlProzess oder der Postgres-Backend-Prozess für Ihre Verbindung? Ich denke, der client ( psql) puffert das Ergebnis irgendwie (oder erzwingt den Backend-Prozess dazu). Wenn Sie copydie Daten verwenden, werden sie niemals an den Client (das psqlProgramm) übertragen, da dies alles auf der Serverseite erfolgt.
psqlProzess aus Syslog : Out of memory: Kill process 26465 (psql). Zu Ihrer Information: Ich führe den Client auf demselben Computer wie den Server aus.
psql - es ist immer noch ein "Client" für den Server. Tritt dies auch auf, wenn Sie den \oBefehl verwenden, um die Ausgabe in eine Datei zu schreiben? In diesem Fall psql"weiß", dass Sie die Daten nicht anzeigen müssen, möglicherweise müssen die Daten dann effizienter abgerufen werden.
COPYpsql -d big -c "copy (select * from big) to stdout" > big.dump