2011-09-19 28 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行记录的批次移动数十亿行的表。这需要一段时间,但我不会在源端或目标端吹出我的服务器内存。