Psycopg2在大型选择查询中占用内存

时间:2015-02-05 11:51:39

标签: python postgresql psycopg2

我正在使用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行表中进行选择?

3 个答案:

答案 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