2015-02-05 14 views
8

Postgresql veritabanını sorgulamak ve tüm satırları yaklaşık 380M satır içeren bir tablodan işlemek için psycopg2 kullanıyorum. Tümü tamsayı olmak üzere yalnızca 3 sütun (id1, id2, count) vardır. Ancak, aşağıdaki açık seçik sorguyu çalıştırdığımda, Python işlemi işletim sistemi tarafından öldürünceye kadar daha fazla bellek tüketmeye başlar.Psycopg2 büyük seçme sorgusunda yukarı belleği kullanır

az bir çalışma örneği (yani mydatabase bulunan ve bir tablo olarak adlandırılan mytable içerir varsayılarak): Bu noktada

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

program belleğini alıcı başlar.

Bir baktım ve Postgresql işlemi iyi çalışıyor. İyi bir işlemci ve iyi bir miktar bellek kullanıyor.

Psycopg2'nin, seçimlerden tüm sonuçları arabelleğe almaya çalışmadan bir yineleyici döndürmesini beklerdim. Sonra tüm satırları işlemek için cur.fetchone()'u tekrar tekrar kullanabilirim.

Peki, kullanılabilir belleği kullanmadan 380M satır tablosundan nasıl seçim yapabilirim?

cevap

12

server side cursors'u kullanabilirsiniz.

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

Harika, bunun için teşekkürler! Açıklamayı biraz iyileştirmek için birkaç düzenleme yapacağım ve kabul ediyorum. – Carl

+0

Bu imleç PostgreSQL sunucusunda veya Python istemcisinde var mı? DECLARE imleç_adı SELECT * SEÇİMİ CURSOR; –

+0

@FrankHeikens Her şey bu durumda Python istemci tarafından yapılır. İmleç sunucu tarafında yok. – Carl

0

sunucu tarafı imleçleri kullanmak için başka bir yol:

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 bir seferde müşteriye itersize satırlar getirmek olacaktır. for döngü bu partiyi tükettiğinde, bir sonraki parçayı getirecektir.