Volver al blog
PostgreSQLIARendimiento

Query plans 81% más rápidos que Postgres con un modelo de 4B

10 de octubre de 2026·6 min de lectura·Diego Horvatti

Un modelo de lenguaje con solo 4 mil millones de parámetros aprendió a armar query plans que corren 81% más rápido que los elegidos por el propio Postgres. Lo cuenta Rohan Bansal en un post sobre el proyecto QORL. Antes de celebrar o de pensar que es puro hype, vale la pena entender qué es un query plan, por qué el optimizador se equivoca y qué cambia este resultado para quien escribe SQL todos los días.

Qué es un query plan y por qué Postgres se equivoca

Cuando mandas un SELECT con cinco JOINs, Postgres no lo ejecuta en el orden en que lo escribiste. Arma un plan. Decide qué tabla leer primero, si usa un índice o hace un seq scan, si el join será nested loop, hash o merge.

Para elegir, estima cuántas filas va a devolver cada etapa. La estimación viene de las estadísticas que recolecta ANALYZE. El problema es que esas estadísticas asumen que las columnas son independientes. En la vida real casi nunca lo son.

Ejemplo clásico: una tabla de direcciones con ciudad y estado. Postgres cree que filtrar por ciudad = 'Guadalajara' y estado = 'Jalisco' reduce las filas dos veces. En la práctica, quien es de Guadalajara ya es de Jalisco. La estimación sale muy baja, elige un nested loop pensando que va a procesar 50 filas y termina procesando 500 mil.

Seguro ya lo viste pasar:

EXPLAIN ANALYZE
SELECT ...
-- Nested Loop (rows=12) (actual rows=480312)

Cuando el rows estimado y el actual rows están separados por tres órdenes de magnitud, el plan ya nació mal. No es un bug de Postgres. Es un problema difícil de verdad. Hay hasta un paper famoso de 2015, "How Good Are Query Optimizers, Really?", que creó el benchmark JOB (Join Order Benchmark) sobre IMDb justamente para exponer estos errores de cardinalidad en todas las bases de datos grandes.

Qué hizo distinto QORL

La idea de usar aprendizaje automático para optimizar query plans no es nueva. Neo (2019) y Bao (2021) ya lo intentaban. Bao, por ejemplo, no reemplaza al optimizador. Elige un conjunto de "pistas" (apaga el nested loop aquí, fuerza un hash join allá) y deja que Postgres arme el plan dentro de esas reglas.

Lo que llama la atención en QORL es que usa un modelo de lenguaje pequeño, de 4B, entrenado para esta tarea. No es un GPT gigante llamado por API en cada query. Es un modelo que corre en una máquina común y que aprendió, mirando la consulta, a proponer un plan mejor que el del optimizador nativo.

El camino más común para aplicar un plan externo en Postgres es la extensión pg_hint_plan, que acepta pistas en un comentario:

/*+ Leading((t mi ci)) HashJoin(t mi) IndexScan(ci ci_movie_id_idx) */
SELECT ...
FROM title t
JOIN movie_info mi ON mi.movie_id = t.id
JOIN cast_info ci ON ci.movie_id = t.id
WHERE ...;

El modelo genera este tipo de cosas y la base de datos obedece. No cambias Postgres, solo le das una segunda opinión.

Lee el post original para ver los detalles de la métrica, porque "81% más rápido" puede significar cosas muy distintas: promedio, mediana, suma del tiempo de un benchmark entero. En benchmarks como JOB, unas pocas queries patológicas suelen dominar el tiempo total. Arreglar tres de ellas ya mueve mucho el número final.

El optimizador de Postgres no es tonto. Solo confía demasiado en sus propias estadísticas.

Por qué un modelo pequeño importa más que uno grande

Aquí está la parte que me parece más interesante, y no es el 81%.

Planificar una query en Postgres toma microsegundos o pocos milisegundos. Si pones un LLM de 70B delante de cada consulta, el tiempo de inferencia se come toda la ganancia en cualquier query OLTP. Nadie acepta esperar 800 ms para ahorrar 40 ms.

Un modelo de 4B cambia esa cuenta. Cabe en una GPU modesta, o incluso en CPU con cuantización. Todavía no es lo bastante rápido para correr en cada query de tu app, pero empieza a tener sentido para:

  • reportes analíticos que tardan segundos o minutos
  • jobs nocturnos de ETL
  • dashboards con consultas pesadas y repetitivas
  • queries que ya sabes que dan problemas

En esos casos, gastar 200 ms pensando para ahorrar 20 segundos es negocio cerrado.

Qué cambia en tu código hoy

En la práctica, casi nada cambia mañana. Y está bien. No instales un modelo delante de tu base de datos de producción porque leíste un post. Pero el resultado muestra dónde está el dinero, y puedes atacar el mismo problema con herramientas que ya existen.

1. Mide antes de suponer. Activa pg_stat_statements y descubre qué queries consumen más tiempo total. Normalmente son cinco o seis.

SELECT query, calls, total_exec_time, mean_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

2. Busca errores de estimación. Corre EXPLAIN (ANALYZE, BUFFERS) en esas queries y compara rows con actual rows. Donde la diferencia sea grande, el optimizador está adivinando.

3. Enséñale la correlación a Postgres. El problema de ciudad y estado tiene solución nativa desde Postgres 10:

CREATE STATISTICS direccion_ciudad_estado (dependencies, ndistinct)
ON ciudad, estado FROM direcciones;

ANALYZE direcciones;

Mucha gente nunca usó CREATE STATISTICS. Es la forma más barata de corregir buena parte de los planes malos, y no exige nada de IA.

4. Aumenta la muestra donde importa. Las columnas con distribución sesgada se benefician de más muestreo:

ALTER TABLE pedidos ALTER COLUMN status SET STATISTICS 1000;
ANALYZE pedidos;

5. Usa hints solo como último recurso. pg_hint_plan resuelve, pero congela una decisión. Cuando los datos cambien, el plan forzado puede convertirse en el peor plan posible. Y nadie se va a acordar de ese comentario mágico dentro de un año.

Las objeciones que valen la pena

"¿Entonces el optimizador va a ser reemplazado por IA?" No tan pronto. El optimizador tradicional tiene una cualidad que ningún modelo tiene todavía: es predecible. Puedes explicar por qué eligió ese plan. Cuando un modelo propone un plan raro, depurar se vuelve mucho más difícil.

"¿Y si el modelo se equivoca feo?" Ese es el riesgo real. Una red que acierta el 95% de las veces y empeora las cosas en el otro 5% puede tumbar producción. Por eso enfoques como Bao trabajan con pistas y mantienen a Postgres al mando. El peor caso importa más que el promedio. Y sí, esto vale para quien nunca tuvo un incidente a las 3 de la mañana por culpa de un nested loop. Todavía.

"¿Funciona en mi schema?" Depende. Los modelos entrenados en benchmarks tienden a aprenderse el benchmark. Tu e-commerce con 40 tablas y datos sucios no es IMDb. La generalización es la pregunta que todo trabajo de este tipo tiene que responder, y es lo primero que miraría antes de confiar.

Mi opinión

Me gusta este tipo de resultado porque es honesto sobre dónde puede ayudar la IA. No es un chatbot escribiendo SQL por ti. Es un modelo pequeño atacando un problema viejo, bien definido y con una métrica clara: la query quedó más rápida o no.

Creo que el futuro aquí es híbrido. El optimizador tradicional sigue al mando y un modelo liviano sugiere correcciones en las queries analíticas pesadas, donde el costo de la inferencia se paga solo. Hasta que esto se vuelva una extensión estable de Postgres, la mejor inversión sigue siendo lo básico bien hecho: pg_stat_statements, EXPLAIN ANALYZE y CREATE STATISTICS. Eso ya resuelve más problemas de lo que parece.

Si te gusta ver este tipo de optimización aplicada en proyectos reales, échale un vistazo a lo que vengo construyendo en mis proyectos.

Resumen para LinkedIn

Un modelo de 4B armó query plans 81% más rápidos que los del propio Postgres.

El optimizador no es tonto. Solo confía demasiado en sus propias estadísticas y cree que ciudad y estado son columnas independientes.

Lo que más me llamó la atención ni siquiera fue el número. Fue el tamaño del modelo: 4B corre en una máquina común y ya compensa en reportes pesados, ETL y dashboards.

Pero antes de poner IA delante de la base de datos, haz lo básico: pg_stat_statements, EXPLAIN ANALYZE y CREATE STATISTICS. Eso ya resuelve más planes malos de lo que parece.

Escribí el paso a paso completo en el blog. ¿Cuál fue la peor query que te tocó cazar?

#PostgreSQL #SQL #Rendimiento #InteligenciaArtificial #DesarrolloBackend