繁体   English   中英

Python psycopg2游标

[英]Python psycopg2 cursors

从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

现在,这在文档中还不是很明显,但是实际上可以在事务期间临时创建此类游标。 无需使用特定的SLQ语句等显式创建返回数据库中的refcursor的函数。使用psycopg2,您仅需在获取游标时给出名称,便会为该事务创建一个临时游标。 所以代替:

 cursor = conn.cursor()

您只需要:

 cursor = conn.cursor('mycursor')

就是这样,它起作用了。 我假设在使用JDBC和设置fetchSize的情况下,相同的操作都是在后台进行的。 它只是更加透明。 在此处查看文档: https : //jdbc.postgresql.org/documentation/head/query.html#query-with-cursor

您可以通过查询同一事务内的pg_cursors视图来测试此方法是否有效。 获取客户端游标后,服务器端游标出现,而关闭客户端游标后,服务器端游标消失。 因此,最重要的是:我很高兴对我的代码进行更改,但是我必须说,对于那些没有使用postgres的人来说,这是一个很大的难题。

实际上,您已经回答了问题;)。

  1. 是的,您应该使用服务器端光标来获取流式传输的记录http://initd.org/psycopg/docs/usage.html#server-side-cursors

从文档:

CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS $$
BEGIN
    OPEN $1 FOR SELECT col FROM test;
    RETURN $1;
END;
$$ LANGUAGE plpgsql;

并在代码中:

cur1 = conn.cursor()
cur1.callproc('reffunc', ['curname'])

cur2 = conn.cursor('curname')
for record in cur2:     # or cur2.fetchone, fetchmany...
    # do something with record
    pass
  1. 是的,如果您想使用服务器端游标获取行,则应该打开新游标。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM