2011-09-19 45 views
1

我有一個約9百萬行的查詢結果集。使用Python/PyGreSQL,我如何有效地處理大型結果集?

我需要爲每一行做一些處理,並且代碼目前做到這一點:

query = conn.query(sql) 
results = query.getresult() 

for row in results: 
    # blah 

我不知道,但我想,getresult()被拉下整個結果集。是這樣嗎?我想有一種方法可以根據需要將結果集的塊大小分開,但在pg模塊文檔中我沒有立即看到類似結果。

是否有可能使用pgdb模塊來代替這個模塊,或者使用其他方法?

我的問題是關於應用程序機器上的內存 - 如果我能幫上忙,我寧願不將一百萬行同時載入內存。

這更值得擔心嗎?

+0

根據pygresql文檔,getresult返回一個pyquery對象,其中各種列表包含關聯查詢的所有數據。您需要查看python的替代數據庫訪問庫是否包含查詢結果的迭代器。 –

回答

2

如果它是繼Python Database API spec創建的,你可以使用光標:

curs = conn.cursor() 
curs.execute('select * from bigtable') 

然後使用curs.fetchone()curs.fetchmany(chunksize)

+0

我在'iter(curs.fetchone())中使用了'行:' - 也許這是額外的顯式?它按預期工作。 –

+0

@anonymous:???如果它跟隨數據庫API,則curs.fetchone()將獲取第一行。迭代它可以爲您提供第一行的列值。也許你的意思是爲了在iter中行(curs.fetchone,None):' –

0

我不知道如何getresult()的行爲,但另一種選擇是PL/Python

的PL/Python過程語言允許PostgreSQL的功能,在Python語言編寫。

這會讓你在數據庫中工作。這可能不適合你需要做的事情,但值得一看。

1

pgdb的遊標迭代

cursor = conn.cursor() 
cursor.execute(sql) 

for row in cursor: 
    # do something with row 

其中connpgdb.connect(...)

+0

幫助我理解:作爲一個「迭代器」,是否意味着整個結果集不是*加載到內存中,而只是根據需要從每個迭代中從postgres服務器中提取出來? –

+0

@anonymouscoward:是;如果沒有結果,'cursor.next()'只調用'fetchone()'並且引發'StopIteration'。將遊標作爲迭代器而不是手動調用'fetchone()'可能更加pythonic。 – geoffspear

0

使用cursor.fetchmany()並確保顯式設置arraysize來處理行集合,以便在性能和內存利用率之間爲您提供所需的平衡。

我有cx_Oracle(它也使用DB-API規範)編寫的作業,並使用它在整個網絡中以20,000行記錄的批次移動數十億行的表。這需要一段時間,但我不會在源端或目標端吹出我的服務器內存。