Skip to content

Repository files navigation

slowquery

Read a Postgres query plan in plain English.

Paste an EXPLAIN ANALYZE plan. Find out which node is actually eating the time, why the planner chose badly, and what to do about it.

CI License: MIT

slowquery diagnosing a slow query: a nested loop consuming 83% of the time, a wasteful sequential scan, and a bad row estimate

Why this exists

EXPLAIN ANALYZE tells you everything and explains nothing. It is dense, deeply nested, and reports its most important number in a form that hides it.

The existing options are explain.depesz.com, which is excellent and about fifteen years old, and pgMustard, which is good and costs money. There is room for something free, modern, and opinionated about what actually matters.

What it tells you

Where the time really went. The plan reports cumulative, per-loop times. slowquery reports exclusive time: children subtracted, loop count multiplied back in.

That distinction is the whole game. A line reading actual time=0.050..0.050 ... loops=40000 looks like nothing and is two full seconds of work. It is the single most commonly missed line in a slow plan, and Postgres never does that multiplication for you.

Why the planner chose badly. A row estimate that is off by three orders of magnitude explains every bad join decision above it. Fixing the estimate often fixes the plan without touching the query.

What to actually do. Where there is an honest single answer, you get it:

An index on status would let it jump straight to the matching rows: CREATE INDEX CONCURRENTLY ON orders (status);

Where there isn't, you get prose instead of a confidently wrong CREATE INDEX somebody runs in production.

What it deliberately doesn't do

It stays quiet when a plan is fine. "Nothing obviously wrong" is a genuinely useful answer, and most tools refuse to give it because empty output feels like failure.

It won't flag a sequential scan that's doing its job. Reading a whole table to return the whole table is usually correct, and indexing a 300-row lookup helps nobody. A scan is only flagged when it is both large and discarding most of what it reads.

It reports each cause once. A bad row estimate propagates upward — the scan misjudges, so the join above it does, so its parent does. Naming every link says the same thing three times and buries everything else, so only the node that actually went wrong is named.

It ranks by cost, not by how alarming something looks. A wasteful scan accounting for 3% of the query is real, but it is not why you are here.

Privacy

Everything runs in your tab. Query plans leak schema, table sizes, index names and sometimes literal values from your data — so this one doesn't send them anywhere. There is no server to send them to; the build is a folder of static files.

Try it

git clone https://github.com/BleakMidwinter90/slowquery.git
cd slowquery
npm install
npm run dev
Command What it does
npm run dev Development server
npm run build Static production build
npm test Unit tests
npm run smoke End-to-end test in a real browser
npm run serve Serve the build on your network

How it works

parse.ts turns the text into a tree. It is deliberately tolerant — the format has no published grammar and two decades of quirks, so anything it can't interpret is kept verbatim rather than dropped. A tree with one odd line in it beats an error message when you're debugging at 2am.

diagnose.ts turns the tree into findings. Both are pure functions with no DOM, covered by 40 tests — including tests that each rule stays quiet when it should, which is the harder half.

Contributing

New rules are very welcome. The bar is that a rule must tell someone something they could not trivially have read off the plan themselves, and must be conservative enough that acting on it blindly won't hurt.

npm test && npx eslint . && npm run typecheck && npm run build && npm run smoke

License

MIT.

About

Read a Postgres query plan in plain English. Paste EXPLAIN ANALYZE, find out what is actually slow and why. Runs entirely in your browser.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages