Psycopg2 usa la memoria en una consulta de selección grande

Estoy usando psycopg2 para consultar una base de datos Postgresql y tratar de procesar todas las filas de una tabla con aproximadamente 380M filas. Solo hay 3 columnas (id1, id2, conteo) todas de tipo entero. Sin embargo, cuando ejecuto la siguiente consulta de selección directa, el proceso de Python comienza a consumir más y más memoria, hasta que el sistema operativo lo detiene.

Ejemplo de trabajo mínimo (asumiendo que mydatabase existe y contiene una tabla llamada mytable):

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

En este punto el progtwig comienza a consumir memoria.

Eché un vistazo y el proceso de Postgresql se está comportando bien. Está utilizando un poco de CPU, lo que está bien, y una cantidad muy limitada de memoria.

Esperaba que psycopg2 devolviera un iterador sin intentar amortiguar todos los resultados de la selección. Entonces podría usar cur.fetchone() repetidamente para procesar todas las filas.

Entonces, ¿cómo selecciono de una tabla de filas de 380M sin utilizar la memoria disponible?

Puede utilizar cursores del lado del servidor .

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

Otra forma de usar los cursores del lado del servidor:

 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 filas de itersize para el cliente a la vez. Una vez que el bucle for agote ese lote, buscará el siguiente.