Developer & cloud explorers

Query Plan Visualizer

PostgreSQL EXPLAIN (ANALYZE) or MySQL EXPLAIN JSON → plan tree, hot nodes and index suggestions.

PostgreSQL: EXPLAIN (ANALYZE, BUFFERS) … as text, or EXPLAIN (ANALYZE, FORMAT JSON). MySQL: EXPLAIN FORMAT=JSON …. psql headers, "+" line continuations and "(N rows)" footers are ignored.

Read in memory as UTF-8 text and not stored. Max 5 MiB.

×

Ratio between estimated and actual rows per loop.

Try an example: PostgreSQL EXPLAIN ANALYZE: seq scan, disk sort, batched hash · PostgreSQL JSON: nested loop with a misestimate · MySQL EXPLAIN FORMAT=JSON: full scan + filesort

How it works

Paste PostgreSQL EXPLAIN / EXPLAIN ANALYZE output (text or FORMAT JSON) or MySQL EXPLAIN FORMAT=JSON. The plan is drawn as a node tree with cost, estimated vs actual rows, inclusive and exclusive time per node, and checked for the classic problems: row misestimates, sequential scans that discard most rows, sorts and hashes spilling to disk, nested loops over large inputs — each with a concrete fix such as a specific CREATE INDEX statement or work_mem setting.

  • PostgreSQL text plans are parsed by the "->" indentation; node headers give cost=startup..total rows width and (actual time=startup..total rows loops); detail lines (Filter, Rows Removed by Filter, Sort Method, Buckets/Batches, Buffers…) are mapped to the same keys as FORMAT JSON.
  • Actual time and rows are per-loop averages (PostgreSQL docs), so inclusive time = actual total time × loops; exclusive time = inclusive − children's inclusive time. Under Gather, time is divided by the number of participating processes.
  • Misestimate = max(estimated, actual)/min(…) rows per loop at or above the threshold (and ≥100 rows absolute difference).
  • Rules: Seq Scan with Filter removing ≥90% of ≥1000 rows; Index Scan still filtering; Sort Method external/Disk; Hash Batches > 1; Nested Loop with ≥1000 outer rows and a sequential inner side or ≥10k inner loops; lossy bitmaps; workers not launched; heap fetches in index-only scans.
  • Index candidates take equality-compared filter columns first, then the first range column (B-tree column-order rule); functions in filters call for expression indexes and leading-wildcard LIKE for pg_trgm.
  • MySQL: access_type ALL / index, filtered %, attached_condition columns, using_join_buffer, using_filesort and using_temporary_table (EXPLAIN FORMAT=JSON has estimates only, no timings).

For scripts and AI agents

  • JSON API: POST https://queryplanvisualizer.usefulweb.site/api/v1/calculate (same calculation as this page)
  • Interface description: OpenAPI 3.1 · AI guide: llms.txt
  • MCP server (Streamable HTTP): https://queryplanvisualizer.usefulweb.site/mcp · tool name query_plan_visualizer
Example request
curl -s -X POST https://queryplanvisualizer.usefulweb.site/api/v1/calculate \
  -H 'content-type: application/json' \
  -d '{…see OpenAPI examples…}'

Related tools

Feedback