
The Hacker News thread exploded. "81% faster query plans than Postgres" was the headline, and it hit me like a jolt. Rohan Bansal had just published QORL: training a 4B model to produce faster Postgres query plans, a post describing a 4B language model fine-tuned to emit PostgreSQL planner hints. It got 667 points and 136 comments. Everyone seemed to be asking the same thing: is the built-in Postgres optimizer finally obsolete? The answer, like most things in engineering, is far more nuanced.
First, let's get the headline numbers straight. That "81% faster" refers to a 44.7% reduction in query latency across the 113 queries in the Join Order Benchmark. To translate a latency reduction into a speedup multiplier, you calculate 1 / (1 - 0.447), which gives you 1.81x. So yes, the model achieved an 1.81x geometric mean speedup on the benchmark workload, improving 68 of 113 queries with zero regressions. That "zero regressions" part is the actual, genuinely exciting claim, and it's what every previous attempt at learned optimizers failed to deliver in production.
But here's where it gets messy. That 1.81x speedup wasn't from a single inference. It was a "best-of-3 rollouts" scenario, meaning the model generated three candidate plans, and the best one was chosen. When you look at an apples-to-apples comparison of a single model inference per query, the geometric mean speedup drops to 1.41x, and the total workload speedup goes from 1.81x down to 1.29x. This difference matters immensely when you're thinking about real-world use.
The Real Cost of "Best-of-3"
Running three inferences and evaluating three plans per query might be fine for a nightly analytics job that takes hours anyway. But for an interactive dashboard or an API endpoint, that added latency for multiple rollouts could easily outweigh the performance gains. You're trading inference time and plan evaluation time for a potentially better plan. For my work at Placewise AI, where every millisecond counts in voice interactions, that tradeoff would be a hard sell.
Here’s a quick breakdown of the cost difference:
| Metric | Single Rollout | Best-of-3 Rollouts |
|---|---|---|
| Geometric Mean Speedup | 1.41x | 1.81x |
| Total Workload Speedup | 1.29x | 1.81x |
| Inferences per Query | 1 | 3 |
| Plan Evaluations per Query | 1 | 3 |
| Best Use Case | Potentially interactive queries | Nightly jobs, complex analytics |
What QORL highlights isn't the failure of Postgres's search algorithms, but the persistent weakness in its cardinality estimation. The model learns better join orders because it's better at predicting row counts than the default statistics. When Postgres guesses wrong about how many rows a join will return, it picks a bad plan. QORL, after training on 13,646 queries from the Cardinality Estimation Benchmark, learns to make better guesses for that specific workload.
What You Can Do This Week
So, before you start thinking about fine-tuning your own 4B model, let's talk about what you can do today to address slow queries. The first step is always to understand where your planner is going wrong. Most of the time, it's those bad cardinality estimates.
- Find Your Worst Offenders
Start with
pg_stat_statementsor your monitoring tools. Identify the queries that consistently take the longest or consume the most resources. - Run EXPLAIN (ANALYZE, BUFFERS)
Don't just run
EXPLAIN. You needANALYZEto see the actual execution times and row counts, andBUFFERSto understand I/O. This is your most powerful debugging tool.EXPLAIN (ANALYZE, BUFFERS) SELECT ... FROM ... WHERE ...; - Compare Estimated vs. Actual Row Counts
Look at the output. For each plan node, compare
rows=(estimated) withactual rows=(what actually happened). If there's a huge discrepancy, say, an estimate of 100 rows but an actual of 100,000, you've found a cardinality estimation problem. This is exactly the kind of issue QORL helps with, but you can fix it manually too.
If your cardinality estimates are good, but your plans are still bad, then QORL's specific win against bad estimates probably won't transfer. You might have a different kind of problem, like an inefficient query structure or missing indexes.
The Boring Fixes That Still Win
The industry isn't waiting around for learned optimizers to become production-ready. Postgres 19's SQL/PGQ graph queries were bounced this month over unresolved bugs, showing the planner is under scrutiny. Agoda recently replaced a 72-shard SQL Server price cache with DragonflyDB, a testament to people working around the planner when it's not meeting their needs. These are real-world workarounds to real-world problems.
For most of us, the "boring" fixes are still the most effective:
- Extended Statistics: Use
CREATE STATISTICS ON (col1, col2) FROM table;to tell Postgres about correlations between columns that it can't infer from single-column statistics. This is a game changer for complexWHEREclauses andJOINconditions. default_statistics_target: Raising this value (e.g., to 1000 or higher) gives Postgres more data to build its statistics from, leading to better estimates. Just be mindful of the added analysis time.- Materialized Views: For slow, repeated analytical queries, pre-calculating and storing the results in a materialized view is often the simplest and most cost-effective solution.
What Rohan Bansal showed is genuinely exciting. It proves that a small, specialized model can learn better join orders than Postgres's cost-based optimizer, particularly when that optimizer is hobbled by bad cardinality estimates. The "zero regressions" claim is what makes it stand out from previous attempts. But for anyone managing a slow analytics workload, the takeaway isn't that AI will magically fix your database. It's that understanding why your planner is struggling, often due to poor cardinality estimates, remains the most important skill. The model just exposed a known weakness, and gave us another, albeit expensive, way to tackle it.
Essays on shipping software and building products. No schedule, no filler.