web-dev-qa-db-ja.com

多数の行の選択時のメモリ使用量

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としてエンコードします

設定の詳細:

  • postgresqlバージョン= 9.3.4
  • work_mem = 1 MB
  • shared_buffers = 128MB
  • effective_cache_size = 128MB
7
JonoB

デフォルトでは、次の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を表し、ヘッダーとフッターの出力を抑制します。

8
Daniel Vérité