psycopg何时执行光标命令

时间:2018-08-23 09:17:08

标签: python postgresql psycopg2

我正在使用psycopg2在数据库上进行简单查询。目前,这是一个只有几个条目的测试数据库,但是我担心我正在执行的命令在迁移到可能很大的真实数据库时会变得太占用内存。

break

所以我的问题是这个。 psycopg2是在import psycopg2 connection = psycopg2.connect('<database_url>') cur = connection.cursor() cur.execute("SELECT * FROM test;") entries = cur.fetchmany(limit) 行中运行数据库查询(在这种情况下,大型数据库将消耗大量客户端内存),还是在execute行中才运行查询(在这种情况下)我可以控制python的内存消耗。)

如果是前者,大概我需要更改SQL查询以仅返回 x 行。

1 个答案:

答案 0 :(得分:1)

要详细说明@Arihant的注释,该语句在调用execute时运行。这将触发数据库的内存消耗。您无需担心(尚未)-大小适中的数据库可以有效处理数百万行。尽管查询本身变得复杂,但是内存开销可能会成为一个问题,尽管有很多优化和内存管理策略正在使用中。

一旦您开始获取数据,客户端内存就会发挥作用。我使用以下两种策略之一来控制内存使用:

使用fetchmany()代替fetchall()(与将光标用作迭代对象相比)。 limit/offset查询可以获得相同的基本结果,但是您需要执行许多这样的查询才能分页浏览大型数据集,这会在服务器上产生不必要的成本。

with conn.cursor() as stmt:
    stmt.execute('select * from big_table')
    rows = stmt.fetchmany(10000)
    while rows:
        for row in rows:
            #do something clever with the row
        rows = stmt.fetchmany(10000)

用户使用服务器端游标。这在服务器上的开销略高,但是将使客户端上的内存完全平整(除非您尝试保留所有记录。

with conn.cursor('my_cursor') as stmt:
    stmt.execute('select * from big_table')
    for row in stmt:
        #do something clever with the row

无论采用何种方法,关键是要处理返回的记录。如果您试图将它们保留在内存中,则会用完内存。分块处理数据。