2015-12-25 7 views
6

私はモデルデータベースにPostgreSQL 9.4を使用します。私のテーブルには、多少のようになります。PythonワークフローでのPostgreSQLのパフォーマンスとメモリ使用の調整

curs.execute("SELECT sid, col1, col2 FROM table1") 
data = curs.fetchall() 
putback = [] 
for i in data: 
    result = do_something(i[1], i[2]) 
    putback.append((sid, result)) 
del data 
curs.execute("UPDATE table1 
       SET col3 = p.result 
       FROM unnest(%s) p(sid INT, result JSONB) 
       WHERE sid = p.sid", (putback,)) 

これは一般的に非常によくかつ効率的に動作します:

CREATE TABLE table1 (
sid INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('table1_sid_seq'::regclass), 
col1 INT, 
col2 INT, 
col3 JSONB); 

私はPython 2.7のワークフローは、多くの場合、このようになります。しかし、大規模なクエリでは、UPDATEコマンドでPostgresqlのメモリ使用量が屋根(> 50GB)を通過することがあり、OS Xによって殺されていると私は信じています。WARNING: terminating connection because of crash of another server processがあるからです。私のMacBook Proには16GBのRAMが搭載されています。問題のクエリには11M行があり、書き戻すデータはそれぞれ約100文字です。

マイpostgresql.conf

default_statistics_target = 50 
maintenance_work_mem = 512MB 
constraint_exclusion = on 
checkpoint_completion_target = 0.9 
effective_cache_size = 4GB 
work_mem = 256MB 
wal_buffers = 16MB 
checkpoint_segments = 128 
shared_buffers = 1024MB 
max_connections = 80 

だから私は

  1. はなぜ私のクエリは、時にはRAMの過剰な量を消費しているだろうか?
  2. どのようにしてメモリの使用を制御し、良好なパフォーマンスを保証できますか?
  3. PostgreSQLをチューニングするためのガイドラインやツールはありますか?

更新
私は@wildplasserは私の問題を正確に指摘することをかなり確信しています。コメントでは、まずデータをデータベースにダンプし、そこから解凍することを提案します。残念ながら、私は彼の提案をどのように実行するかを理解できませんでした。 どのようにすればいいか分かっている人は、その答えが喜んで受け入れられます。

+0

1)あなたのwork_memは(むしろ)高く、おそらくテーブル構造はありません。 2)あなたのデータベースを設計する3)2を参照してくださいBTW:あなたの選択したクエリは*すべての行を取り出します(私はあなたの更新クエリを理解しません)。 – wildplasser

+0

はい。あなたのテーブルはスプレッドシートのように見えるかもしれませんが、わかりません。はい。 – wildplasser

+0

ところで、あなたはPythonに関することを理解していませんが、dbテーブル全体をpythonのセットや配列に吸い込んで、同じテーブルを更新するためにそれを(分解した形で)使用しているようです。 – wildplasser

答えて

1

マイ回避策が提案hereのような単純な機能でputbackをスライスすることです:

def chunk(l, n): 
    n = max(1, n) 
    return [l[i:i + n] for i in range(0, len(l), n)] 

、その後

for chunk in chunk(putback, 250000): 
    curs.execute("UPDATE table1 
        SET col3 = p.result 
        FROM unnest(%s) p(sid INT, result JSONB) 
        WHERE sid = p.sid", (chunk,)) 

これが機能する、すなわち、チェックにメモリフットプリントを保持しますが、いつものようにすべてのデータを一度にダンプするよりもエレガントで遅いです。

関連する問題