我正在编写一个查询数据库结果的小程序(单表)。我正在使用python 3.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%是对数据库进行排队(第一行)。因此,当我开始计划时,我的进度条开始移动之前会有很大的延迟。另外,我不需要将所有结果保存在内存中。我可以单独处理它们。
有没有办法修改上面的程序来逐行获取行,直到收到所有行,而不将所有内容都加载到内存中?另外,我想监视查询和处理数据的进度。
答案 0 :(得分:3)
您只需循环查询,无需调用.all()
,和调用.yield_per()
来设置批量大小:
for row in db_session.query(Data).yield_per(10):
do_something_with_data(row)
.all()
确实将整个结果集转换为 first 列表,如果结果集很大则会导致延迟。设置.yield_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_per()
也是如此。在这种情况下,您需要使用windowed query根据列中一个中的值范围将查询分解为块。这是否有效取决于您的确切表格布局。