从psycopg2文档:Python的psycopg2光标
当执行一个数据库查询,该Psycopg光标通常取了后端返回的所有记录,将它们转移到客户端的过程。如果查询返回了大量的数据,则客户端将分配相当大量的内存。如果数据集太大而无法在客户端实际处理,则可以创建服务器端游标。
我想查询一个可能有数千行的表格,并为每个表格执行一些操作。普通游标实际上是否将整个数据集引入客户端?这听起来不合理。代码是沿线的东西:
conn = psycopg2.connect(url)
cursor = conn.cursor()
cursor.execute(sql)
for row in cursor:
do some stuff
cursor.close()
我希望这是一个流式操作。第二个问题是关于游标的范围。在我的循环内我想要更新另一个表。我是否需要打开一个新的光标并每次关闭?每个项目更新应该在它自己的事务中,因为我可能需要执行回滚。
for row in cursor:
anotherCursor = anotherConn.cursor()
anotherCursor.execute(update)
if somecondition:
anotherConn.commit()
else:
anotherConn.rollback
cursor.close()
========编辑:我的回答第一部分========
好吧,我会尽量回答我的问题的第一部分。在您开始迭代结果集之前,只要您调用execute,普通游标实际上就会带来整个数据集。您可以通过在每个步骤检查进程的内存占用情况来验证。但是对服务器端游标的需求实际上是由于postgres服务器而不是客户端,并且在这里被记录:http://www.postgresql.org/docs/9.3/static/sql-declare.html
现在,这不是立即从文档中显而易见的,但这样的游标实际上可以暂时为交易的持续时间。没有必要显式地创建一个函数,该函数返回数据库中的refcursor,使用特定的SLQ语句等。使用psycopg2,只需在获取游标时提供一个名称,并为该事务创建临时游标。因此,而不是:
cursor = conn.cursor()
你只需要到:
cursor = conn.cursor('mycursor')
这就是它和它的作品。在使用JDBC时,我假设在设置fetchSize时,在封面下做了同样的事情。这只是更透明一点。在此处查看文档:https://jdbc.postgresql.org/documentation/head/query.html#query-with-cursor
您可以通过查询同一事务中的pg_cursors视图来测试它的工作原理。获取客户端游标后出现服务器端游标,并在关闭客户端游标后消失。所以底线:我很乐意为我的代码做这个改变,但是我必须说这对于那些不熟悉postgres的人来说是个大问题。
你能避免所有的交通和做选择和更新在同一查询光标苦差事。发布真正的问题,很可能你会得到更好的答案。 –
我想你的意思是用“update where”语句,对吧?在我的使用案例中,处理比这更复杂。 –
我的意思是一个CTE查询。无论复杂程度如何。 –