Python 逐个从数据库获取结果

Python 逐个从数据库获取结果,python,database,sqlalchemy,Python,Database,Sqlalchemy,我正在编写一个小程序,从数据库(单个表)查询结果。我正在使用Python3.3、sqlalchemy和postgres数据库 result = db_session.query(Data).all() progress = 0 for row in result: update_progress_bar(progress, len(result)) do_something_with_data(row) progress += 1 变量“result”将包含几千行,数据

我正在编写一个小程序,从数据库(单个表)查询结果。我正在使用Python3.3、sqlalchemy和postgres数据库

result = db_session.query(Data).all()
progress = 0
for row in result:
    update_progress_bar(progress, len(result))
    do_something_with_data(row)
    progress += 1
变量“result”将包含几千行,数据处理需要一些时间。这就是为什么我引入了简单的进度条,让大家知道它需要多少时间。 问题是,总时间的30%正在对数据库进行查询(第一行)。所以,当我启动程序时,在进度条开始移动之前,我会有很大的延迟。此外,我不需要将所有结果都保存在内存中。我可以单独处理它们


有没有办法修改上面的程序,在接收到所有行之前逐个获取行,而不将所有内容加载到内存中?此外,我还想监控查询和处理数据的进度。

您只需在查询上循环,而无需调用
.all()
,然后调用以设置批量大小:

for row in db_session.query(Data).yield_per(10):
    do_something_with_data(row)
.all()
确实会首先将整个结果集转换为列表,如果结果集很大,则会导致延迟。在设置
.yield\u per()
后直接迭代查询,而是根据需要获取结果,前提是数据库API支持它

如果您想预先知道将返回多少行,请首先调用
.count()

result = db_session.query(Data)
count = result.count()

for row in result.yield_per(10):
    update_progress_bar(progress, count)
    do_something_with_data(row)
    progress += 1
.count()
要求数据库首先为我们提供项目计数


即使在使用
.yield\u per()
时,数据库仍可能会预缓存结果行,从而导致启动延迟。在这种情况下,您需要使用一个函数根据其中一列中的值范围将查询分解为块。这是否有效取决于您的确切表格布局

您是否有需要的迭代器获取结果的参考?如果我没记错的话,没有多少DBAPI支持流式处理,特别是Sqlite3首先获取所有行。不幸的是,在程序到达主循环之前,我仍然会得到延迟。我忘了提一下,我正在使用PostgreSQL。@Marek:数据库本身很容易需要一些启动时间才能开始提供数据。也可能是数据库API本身不支持流式传输。使用
.all()
可以保证您首先将所有内容加载到内存中,对查询进行迭代至少可以让底层数据库API有机会分批为您提供结果。@Marek:我忘记添加切换到流媒体模式所需的
.yield\u all()
调用。Psycopg2应该支持在此模式下操作。@Marek:
.yield\u per()
为您设置
执行选项。
感谢EOL sugestion,我查看了“流式处理结果”。为了让它工作,我必须使用“.execution\u options(stream\u results=True)”运行查询。我还发现我的数据库适配器(pypostgresql)不支持流。唯一能够做到这一点的是psycop2。幸运的是,新的psycop2.5现在支持python 3.3:)我将测试并分享经验:)