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_dump
etwas Ä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
psql
Prozess 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 copy
die Daten verwenden, werden sie niemals an den Client (das psql
Programm) übertragen, da dies alles auf der Serverseite erfolgt.
psql
Prozess 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 \o
Befehl 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.
COPY
psql -d big -c "copy (select * from big) to stdout" > big.dump