EXPLAIN reveals PostgreSQL’s execution plan, detailing how it scans, joins, and sorts data so you can optimize queries.
The execution plan is PostgreSQL’s step-by-step roadmap for running a query. Each node shows which table access method, join strategy, and sort operation the planner chooses. Inspecting plans uncovers slow scans, missing indexes, and sub-optimal joins.
Use EXPLAIN
before any SELECT, INSERT, UPDATE, or DELETE. PostgreSQL returns a tree with estimated costs, rows, and width. No data is read—only the planner is invoked.
Add ANALYZE
to run the query and overlay actual runtime stats. Add BUFFERS
to see shared-block hits and reads. Use VERBOSE
to expose target column lists and internal details.
FORMAT JSON
returns a structured plan suited for code analysis and visualization tools. FORMAT YAML
provides readable, indented output. Default TEXT works well for psql.
Look for Seq Scan nodes reading many rows with high cost. If a selective predicate exists on an indexed column, create or tweak the index to convert the sequential scan to an Index Scan.
Start at the deepest child node—this is executed first. Compare rows
vs actual rows
; big gaps signal stale statistics. Focus on nodes with the largest actual time
. Use BUFFERS
to find disk reads.
Run ANALYZE
regularly or enable autovacuum so the planner’s row estimates stay accurate, reducing surprise sequential scans.
Yes, if you run it with INSERT, UPDATE, or DELETE, the statement executes and changes data. Wrap the call in a transaction and roll back if you only need the plan.
Use EXPLAIN (FORMAT JSON)
and redirect output to a file, or call pg_store_plans
extension to log plans automatically.
Common causes include low selectivity, mismatched data types (e.g., varchar vs text), or functions on the indexed column. Rewrite predicates or create expression indexes.