Psycopg2 在大型 select 查询上用完了内存

Psycopg2 uses up memory on large select query

我正在使用 psycopg2 查询 Postgresql 数据库并尝试处理来自 table 的所有行,其中约有 380M 行。只有 3 列(id1、id2、count)都是整数类型。但是,当我 运行 下面的直接 select 查询时,Python 进程开始消耗越来越多的内存,直到它被 OS.

杀死

最小工作示例(假设 mydatabase 存在并包含一个名为 mytable 的 table):

import psycopg2
conn = psycopg2.connect("dbname=mydatabase")
cur = conn.cursor()
cur.execute("SELECT * FROM mytable;")

此时程序开始消耗内存。

我看了一下,Postgresql 进程运行良好。它使用了相当多的 CPU,这很好,而且内存量非常有限。

我期待 psycopg2 成为 return 一个迭代器,而不是试图缓冲来自 select 的所有结果。然后我可以重复使用 cur.fetchone() 来处理所有行。

那么,如何从 380M 的行 select table 中提取可用内存而不用完可用内存?

您可以使用 server side cursors.

cur = conn.cursor('cursor-name') # server side cursor
cur.itersize = 10000 # how much records to buffer on a client
cur.execute("SELECT * FROM mytable;")

另一种使用服务器端游标的方法:

with psycopg2.connect(database_connection_string) as conn:
    with conn.cursor(name='name_of_cursor') as cursor:

        cursor.itersize = 20000

        query = "SELECT * FROM ..."
        cursor.execute(query)

        for row in cursor:
            # process row 

Psycopg2 将一次获取 itersize 行到客户端。一旦 for 循环耗尽该批次,它将获取下一批次。