pqsl
を使用してコマンドラインから大きなテーブルの内容全体をダンプしようとしていますが、メモリ使用量が増加し、プロセスが強制終了されるところまで問題が発生していますbeforeすべてのデータがダンプされます。
わからないのは、クエリが結果を返さないすぐに、メモリ不足なしに完了するのはなぜですか? =
これが私が試みていることの正確な説明です:
テーブルがあります。
CREATE TABLE big
(
id integer,
Rand double precision
)
多数の行が挿入されます(5,000万):
insert into big
select generate_series(1, 50000000) AS id, random();
すべての行を選択するクエリプランは次のようになります(当然のことです)。
$ 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)
次に、内容をファイルにダンプしようとします。
$ psql -d big -c "select * from big;" > big.dump
上で述べたように、このコマンドは、データが書き込まれる前に失敗します。これは、OSによって(「OOM killer」によって)強制終了される前に、ますます増加するメモリを消費しているようです。
注:pg_dump
似たようなことを実現するために、実際には私のクエリはこれよりも複雑です。具体的には、ダンプするときに各行をJSONとしてエンコードします。
設定の詳細:
デフォルトでは、次の2つの理由により、結果は完全にメモリにバッファリングされます。
1)-A
オプションを使用しない限り、出力行はalignedなので、psqlが各列の最大長を認識するまで出力を開始できません。大量のメモリに加えて)。
2)FETCH_COUNT
を指定しない限り、psqlはクエリで同期PQexec
関数を直接使用し、結果セット全体をバッファリングします。ただし、FETCH_COUNT
を設定する場合、カーソルベースのメソッドを使用して、連続するフェッチ呼び出しを行い、FETCH_COUNT
行ごとにクライアント側のバッファを解放または再利用します。
したがって、大きな結果セットは次のようなコマンドでフェッチする必要があります。
psql -A -t --variable="FETCH_COUNT=10000" \
-c "select columns from bigtable" \
> output-file
FETCH_COUNT
を使用すると、行が非常に大きくてもメモリを消費しすぎる場合に削減されます。
-t
は--tuples-only
を表し、ヘッダーとフッターの出力を抑制します。