我正在使用psycopg2查询Postgresql数据库并尝试处理大约380M行的表中的所有行。所有类型为整数的列只有3列(id1,id2,count)。但是,当我在下面运行简单的select查询时,Python进程开始消耗越来越多的内存,直到它被操作系统杀死。
最小工作示例(假设mydatabase存在且包含名为mytable的表):
import psycopg2
conn = psycopg2.connect("dbname=mydatabase")
cur = conn.cursor()
cur.execute("SELECT * FROM mytable;")
此时程序开始消耗内存。
我看了一下,Postgresql进程运行良好。它使用了相当多的CPU,这很好,而且内存量非常有限。
我期待psycopg2返回迭代器而不尝试缓冲select中的所有结果。然后我可以反复使用cur.fetchone()
来处理所有行。
那么,如何在不耗尽可用内存的情况下从380M行表中进行选择?
答案 0 :(得分:19)
您可以使用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;")
答案 1 :(得分:4)
使用服务器端游标的另一种方法:
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
循环耗尽该批次,它将获取下一批。
答案 2 :(得分:0)
您可以在Postgresql中将OFFSET选项与自定义LIMIT一起使用,以检索少量数据集。更多信息,请访问:https://www.postgresql.org/docs/8.1/queries-limit.html
例如:
offset = 0
while True:
data = cursor.execute("SELECT * FROM mytable LIMIT 100 OFFSET {}".format(offset))
if not data:
break
for row in data:
# process data
offset += 100