【问题标题】:Psycopg2 uses up memory on large select queryPsycopg2 在大型选择查询中耗尽内存
【发布时间】:2015-02-05 11:51:39
【问题描述】:

我正在使用 psycopg2 查询 Postgresql 数据库并尝试处理大约 380M 行的表中的所有行。只有 3 列(id1、id2、count)都是整数类型。但是,当我运行下面简单的选择查询时,Python 进程开始消耗越来越多的内存,直到它被操作系统杀死。

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

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

此时程序开始消耗内存。

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

我期待 psycopg2 返回一个迭代器,而不尝试缓冲来自选择的所有结果。然后我可以重复使用cur.fetchone() 来处理所有行。

那么,如何在不耗尽可用内存的情况下从 380M 的行表中进行选择?

【问题讨论】:

    标签: python postgresql psycopg2


    【解决方案1】:

    您可以使用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;")
    

    【讨论】:

    • 太好了,谢谢!我将进行一些编辑以稍微改进解释,然后接受。
    • 这个游标是否存在于 PostgreSQL-server 或 Python-client 中? DECLARE cursor_name CURSOR FOR SELECT * FROM mytable;
    • @FrankHeikens 在这种情况下,一切都是从 Python 客户端完成的。服务器端不存在游标。
    • 不,这是错误的。当你创建一个“命名游标”时,psycopg 会在服务器端创建一个相应的游标并为你管理它。
    • @fog:谢谢你的信息!
    【解决方案2】:

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

    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 循环耗尽了该批次,它将获取下一个。

    【讨论】:

      猜你喜欢
      • 2018-11-05
      • 2013-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 2021-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多