DevTools Hub

Search tools

Search for a developer tool

SQL

SQL Explain Helper

Find the actual bottleneck in a PostgreSQL EXPLAIN ANALYZE plan.

Parses standard PostgreSQL EXPLAIN / EXPLAIN ANALYZE text output specifically. Other formats (MySQL tabular, JSON plans) still get keyword matches below.

Planning: 0.512 msExecution: 15.89 ms
Slowest steps (by actual time, excluding children)
  1. Seq Scan on orders o10.20 ms · 64%
  2. Hash Join2.70 ms · 17%
  3. Seq Scan on users u1.20 ms · 8%
  4. Hash0.70 ms · 4%
  5. Sort0.49 ms · 3%
Things worth a look
  • Seq Scan on orders oSequential scan reading ~49872 rows — consider whether an index would help.
  • Seq Scan on users uSequential scan reading ~1180 rows — consider whether an index would help.
Terms found in your plan
  • Seq ScanReads every row in the table, in physical order. Fine for small tables; a red flag for large ones if only a few rows are actually needed.
  • Hash JoinBuilds a hash table from one input, then probes it with the other. Typically fast for larger equi-joins.
  • SortSorts rows — used for ORDER BY, merge joins, or grouped aggregates. Can spill to disk if it doesn't fit in memory.
  • FilterA condition applied after rows are read, discarding non-matching ones — unlike an index condition, a Filter doesn't reduce how much was read in the first place.
  • Rows Removed by FilterHow many rows a Filter discarded after they were already read — a high number here often means an index on the filtered column would help.

What this does

Paste the output of EXPLAIN or EXPLAIN ANALYZE (PostgreSQL's standard text format) and this reconstructs the plan tree, then computes each step's own cost or time — excluding whatever its child steps already accounted for. That distinction matters: the top node in a plan always shows the largest cumulative cost, since it includes everything beneath it, which makes it easy to misread the outer node as "the slow part" when the actual bottleneck is buried three levels down. Ranking by self time instead of cumulative time points at the step that's actually expensive.

Scope and limitations

This parses PostgreSQL's standard indented text output specifically — not MySQL's tabular EXPLAIN, not any database's JSON or XML plan format, and not SQL Server's graphical plans. When the input doesn't match that format, the tree analysis is skipped, but plan-related terms found anywhere in the text (MySQL's Extra column values included) are still matched against the glossary below, so pasting a different format still gets you some value.

It also isn't a substitute for actually understanding your query or your data — the flags it raises (a large sequential scan, a big gap between estimated and actual row counts, a filter discarding more rows than it kept) are heuristics worth a second look, not guaranteed problems. A sequential scan on a small table is often exactly the right plan.

Term glossary

How this is computed

Parsing and analysis happen entirely in your browser via a small hand-written parser — a query plan can reveal table names, column names, and row counts you might not want to paste into a random web form, so nothing here is ever sent anywhere.

Try it yourself

If you're staring at the query itself rather than its plan, How to Read Complex SQL Queries covers the reading side. Reformat a messy query first with SQL Formatter before you go looking for why it's slow.

Related tools