Back to the blog
PostgreSQLDatabasesAI

A 4B model beats the Postgres optimizer: what changes

October 01, 2026·6 min read·Diego Horvatti

Rohan Bansal trained a 4 billion parameter language model to build query execution plans. According to him, the plans came out 81% faster than the ones from the Postgres optimizer. The project is called QORL and it's described on his blog. Four billion parameters to decide the order of a JOIN. Hard to find anything more 2026 than that.

The number grabs attention. But before anyone suggests replacing the production database planner with an LLM, it's worth understanding what's at stake. I want to show where the Postgres optimizer gets it wrong, why a small model can beat it, and what you can already use today, with no AI at all.

How the Postgres optimizer picks a plan

When you send a SELECT across five tables, Postgres doesn't run it right away. First it considers several ways to solve the query. Which table to read first. Whether to use an index or a seq scan. Whether to join with a nested loop, a hash or a merge. Each path gets an estimated cost, and the cheapest one wins.

The problem is the word "estimated". The cost depends on how many rows the planner thinks each step will return. That guess comes from the statistics ANALYZE collects: histograms, most common values, distinct counts. By default, the planner treats each column as independent from the others.

In real life, columns are correlated. Think of an addresses table:

SELECT * FROM addresses
WHERE city = 'Curitiba' AND state = 'PR';

Postgres multiplies the selectivity of city by the selectivity of state, as if they were unrelated. But every row with Curitiba is already in Paraná. The estimate ends up far below reality. On a single table, that's noise. Across six chained joins, the error compounds at every step. The planner picks a nested loop thinking it will process 40 rows, when it will actually process 400 thousand.

The Postgres optimizer isn't dumb. It's blind to correlation.

This diagnosis is old news. The 2015 paper "How Good Are Query Optimizers, Really?" showed that cardinality estimation errors matter far more than the cost model itself. There's also a practical limit. Above 12 tables in the FROM (the default geqo_threshold), Postgres gives up on exhaustive search and switches to a genetic algorithm. It works, but it's approximate.

Where a 4B model fits in

The idea of a "learned optimizer" isn't new. Neo (2019) and Bao (2021) already trained models to pick plans or steer the planner with hints. What's new here is using a small language model, the kind that runs on a single GPU, and training it on outcomes. A plan is judged by how long it takes to run, not by the cost Postgres calculates. The "RL" in QORL stands for reinforcement learning, and that approach fits the problem. You don't need a dataset of "correct plans". You just run and measure.

In practice, the most common way to apply an external plan in Postgres is the pg_hint_plan extension. You describe the join order and methods, and the database obeys:

/*+ Leading((o i) c) HashJoin(o i) IndexScan(c customers_pkey) */
SELECT c.name, sum(i.total)
FROM orders o
JOIN items i ON i.order_id = o.id
JOIN customers c ON c.id = o.customer_id
WHERE o.created_at > now() - interval '7 days'
GROUP BY c.name;

A model that generates this kind of output doesn't need to know the exact cost of anything. It only needs to have seen, during training, that a certain query shape with a certain data profile runs better with a hash join than a nested loop. It trades math for experience, like a veteran DBA does.

And size matters. A 4B model can be served locally with low latency. A frontier model would spend more time planning than Postgres spends executing most queries.

What "81% faster" means (and what it doesn't)

Here comes the skeptical part. Optimizer benchmarks are full of traps, and a few questions are always worth asking:

  • Which workload? Research in this area usually relies on JOB (Join Order Benchmark, built on IMDB data) or TPC-H/TPC-DS. These are workloads with lots of joins and correlated data, exactly where Postgres struggles most. Your CRUD API looks nothing like that.
  • Average or tail? A big average gain can come from a handful of queries that went from 2 minutes to 3 seconds. What matters in production is how many queries got worse, and by how much.
  • Was inference time counted? Planning a query in Postgres takes microseconds or a few milliseconds. An LLM, even a small one, takes much longer. For long analytical queries, that disappears in the total. For a SELECT by primary key, it becomes the bottleneck.
  • What happens when the data changes? The model learned from one distribution. If the orders table triples on Black Friday, does it still get it right?

None of this invalidates the work. It's research, and the result is impressive for a model this size. You just can't read "81%" and conclude your database will get 81% faster. Bao, for example, already showed strong gains on analytical workloads, and it still never became standard in production. Predictability counts for a lot when your pager goes off at 3 a.m.

Why this matters even if you never use QORL

The most useful takeaway from the project isn't about AI. It's about where the room for improvement is. If a model learns to beat the planner, it's because the planner systematically leaves performance on the table. And you can recover a good chunk of that with tools that already ship with Postgres.

The first is looking at the gap between estimated and actual:

EXPLAIN (ANALYZE, BUFFERS)
SELECT ...;

Look for nodes where the estimated rows= and actual rows= differ by 10x or more. That's where the planner is guessing wrong, and that's where it picks the wrong join.

The second is teaching Postgres about correlation. Extended statistics have been around since version 10:

CREATE STATISTICS addresses_city_state (dependencies, ndistinct, mcv)
  ON city, state FROM addresses;

ANALYZE addresses;

With that, the planner stops treating city and state as independent. I've seen a report query drop from 40 seconds to under 2 with just that, without touching a single index.

The third is increasing the sample size for the columns that matter:

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

The default is 100. On columns with a very skewed distribution, a bigger sample already improves estimates a lot.

Should you put AI in your database planner?

Today, for almost everyone, no. Inference latency, regression risk and the lack of official integration keep this in the lab. If you run a regular web app on Postgres, the gains are in EXPLAIN ANALYZE, well thought out indexes and better statistics.

Where I think it will catch on first is data warehouses and repetitive analytical workloads. There, the same 200 queries run every day, each one takes minutes, and a model can be trained specifically on them. Planning in 100 ms to save 30 seconds is an obvious trade. I can also picture a middle ground. The model suggests hints offline, someone reviews them, and only the ones that prove a gain become a fixed pg_hint_plan on the critical query.

My take: QORL shows that a small, specialized model trained on real rewards beats generic heuristics on well defined problems. That lesson applies far beyond databases. But the Postgres optimizer isn't going anywhere anytime soon. It's fast, predictable, and it fails in ways you can understand and fix. On most days, predictable beats brilliant.

If you want to see how I handle Postgres in real projects, take a look at my projects.

LinkedIn summary

A 4 billion parameter model built query plans 81% faster than the ones from the Postgres optimizer.

Before you swap your production planner for an LLM, it's worth understanding why. Postgres isn't dumb. It just can't see correlation between columns.

It multiplies estimates as if city and state had nothing to do with each other. Across six joins, that error picks a nested loop for 40 rows when 400 thousand actually show up.

The good news is you can get a lot of that gain back today, without AI: EXPLAIN ANALYZE, CREATE STATISTICS and a bigger sample on the right columns. I've seen a report go from 40 seconds to under 2 with just that.

On most days, predictable beats brilliant.

I wrote about QORL, what that "81%" means and what it doesn't. Link in the comments.

#PostgreSQL #Databases #ArtificialIntelligence #Performance #SoftwareDevelopment