2015-02-05 2 views
8

psycopg2를 사용하여 Postgresql 데이터베이스를 쿼리하고 약 380M 행의 테이블에서 모든 행을 처리하려고합니다. 모든 정수 유형의 열 (id1, id2, count)은 3 개뿐입니다. 그러나 아래의 간단한 select 쿼리를 실행하면 Python 프로세스가 OS에서 kill 될 때까지 점점 더 많은 메모리를 사용하기 시작합니다.Psycopg2가 대량 선택 쿼리에서 메모리를 사용합니다.

최소한의 작업 예 (즉하여 MyDatabase이 존재하고 테이블이라고 MYTABLE가 들어 가정) :이 시점에서

import psycopg2 
conn = psycopg2.connect("dbname=mydatabase") 
cur = conn.cursor() 
cur.execute("SELECT * FROM mytable;") 

프로그램이 메모리를 소모 시작합니다.

나는 외관이 좋았고 Postgresql 프로세스가 잘 작동하고 있습니다. CPU 사용량이 적당하고 메모리 용량이 매우 적습니다.

psycopg2가 select의 결과를 모두 버퍼링하지 않고 반복기를 반환 할 것으로 예상했습니다. 그런 다음 cur.fetchone()을 반복적으로 사용하여 모든 행을 처리 할 수있었습니다.

그럼 사용 가능한 메모리를 사용하지 않고 380M 행 테이블을 선택하려면 어떻게해야합니까?

답변

12

server side cursors을 사용할 수 있습니다.

cur = conn.cursor('cursor-name') # server side cursor 
cur.itersize = 10000 # how much records to buffer on a client 
cur.execute("SELECT * FROM mytable;") 
+0

대단히 감사합니다. 약간의 설명을 좀 더 잘하고 받아 들일 수 있도록 몇 가지 편집을 할 것입니다. – Carl

+0

이 커서는 PostgreSQL 서버 또는 Python 클라이언트에 있습니까? DECLARE cursor_name CURSOR FOR SELECT * from mytable; –

+0

@FrankHeikens이 모든 경우 파이썬 클라이언트 측에서 처리됩니다. 서버 측에 커서가 없습니다. – Carl

0

서버 측 커서를 사용하는 또 다른 방법 :

with psycopg2.connect(database_connection_string) as conn: 
    with conn.cursor(name='name_of_cursor') as cursor: 

     cursor.itersize = 20000 

     query = "SELECT * FROM ..." 
     cursor.execute(query) 

     for row in cursor: 
      # process row 

Psycopg2 한 번에 클라이언트에 itersize 행을 가져옵니다. for 루프가 해당 일괄 처리를 소모하면 다음 일괄 처리를 가져옵니다.

관련 문제