← Volver al blog
·8 min de lectura·

Python y Postgres: deje de meterse la tabla en memoria

El SQL puede estar bien y la API igual se cae: .all() sin tope, consultas con f-string, N+1 del ORM, una conexión nueva por petición, pandas como almacén en la caja web. Cómo dejo Python delgado alrededor de Postgres en 2026.

PythonPostgreSQLFastAPISQLRendimientoIngeniería

El artículo de SQL es la consulta. Este es el Python que se niega a deshacerla. Sigo viendo el mismo accidente: una ruta FastAPI limpia, un modelo SQLAlchemy limpio y 200 MB de working set porque scalars().all() significaba «todo». La base hizo su trabajo. La app pidió un CSV del almacén.

Ya escribí las cinco formas SQL que uso en vez de un bucle. Aquí va el sobre: parámetros, un pool, un timeout y la disciplina de no recoger una tabla porque la API del dataframe es cómoda.

1. El script que iba bien con 800 filas

Dump local, pandas, un groupby, un to_excel. Luego alguien lo apunta a producción «solo para este informe». Eso no es un informe. Es un extracto de la base primaria en un proceso que el OOM va a matar. Si la respuesta es un número, una lista de cincuenta filas o un archivo que puede streamear, no recoja la tabla. Escribo la agregación en SQL — o una vista materializada si es diaria — y dejo Python como sobre: auth, parámetros, formato.

2. Los f-string no son una API de consultas

Armar SELECT * FROM orders WHERE id = {order_id} con un f-string es regalar la base. Use $1, %(id)s o parámetros ligados. Cada driver los tiene. SQLAlchemy text() también. Un LLM que concatena SQL es el mismo bug con mejores maneras. Misma familia: listas IN uniendo cadenas. Use ANY($1::int[]) o un bind de verdad. No «escapo» de esto.

3. El N+1 del ORM que parece Python limpio

for invoice in invoices: invoice.customer.name es una consulta de más por fila. selectinload, un join o una consulta de lista aparte. «Luego añado un loader» es cómo muere la página de lista tras una feria. Uso un ORM para escrituras que coinciden con la unidad de trabajo: crear pedido y líneas en una sesión. SQL para listas y exportaciones. Lo híbrido no es un fracaso. Un ORM que esconde cuatrocientas consultas sí.

4. Una conexión por petición no es un pool

Abrir psycopg en cada handler, o crear un engine dentro de la función, es cómo choca con max_connections en un deploy. Un engine o un pool async por proceso. Timeout al acquire. Un checkout que no puede vivir a través de un await que llama a otro servicio. asyncpg o psycopg 3 en el camino caliente que controlo. SQLAlchemy si el equipo ya piensa en sesiones y necesito migraciones más identity map. No arranco tres ORM porque un tutorial usaba Django.

5. Pandas es una segunda base — trátalo así

Un groupby de pandas sobre un frame de dos gigas es una consulta de almacén en una caja de API. Si necesita pandas, el extracto ya debe ser estrecho: las columnas que usa, el día que necesita, un COPY o un cursor en servidor. chunksize existe. fetchmany existe. yield existe. Me gusta pandas en notebooks de análisis. No me gusta como implementación de /stats. Esa ruta es SQL más un dict tipado.

6. Lo que entrego de verdad

Un router FastAPI. Parámetros validados — fechas, id de espacio, un límite. Una función que corre una consulta parametrizada, a menudo las formas de ventana del otro artículo. Un pool. Un statement timeout para que un mal plan tumbe la petición, no la instancia. Sin SELECT *. Sin un .all() silencioso sobre una tabla sin tope. Una petición, una transacción, salvo una razón con nombre — outbox, un traspaso de pago. El aislamiento se queda en READ COMMITTED hasta que pueda nombrar la anomalía que temo.

Conclusión: el pegamento sí, un segundo almacén no

Python es el mejor pegamento que tengo para HTTP y jobs. Se encarece cuando se hace pasar por Postgres. Escriba la consulta, ligue los parámetros, streamee o agregue, y deje el proceso pequeño. El bucle listo puede esperar. La base ya tenía uno mejor — ese es el otro artículo.

¿Hablamos de tu proyecto?

Soy ingeniera web senior, especializada en React y Next.js - disponible para proyectos freelance en cualquier país.

Ubicación

Kyiv, Ucrania

Telegram

Contáctame

WhatsApp

Contáctame