data-peek
Features

Query Plans

Analyze query performance with EXPLAIN ANALYZE

Query Plans

Use EXPLAIN ANALYZE to understand how PostgreSQL executes your queries and optimize performance.

Running EXPLAIN

  1. Write your SELECT query
  2. Execute the query to see results
  3. Click Explain or Explain Analyze in the toolbar

Modes

ModeDescription
EXPLAINShows estimated plan without executing
EXPLAIN ANALYZERuns query and shows actual statistics

EXPLAIN ANALYZE actually executes the query, so use with caution on slow queries or data-modifying statements.

Plan Viewer

Node Tree

The plan displays as a collapsible tree:

Aggregate (cost=1000..1001 rows=1)
  └── Index Scan on users_pkey (cost=0..900 rows=10000)
        Index Cond: (active = true)

Node Information

Each node shows:

MetricDescription
Node TypeType of operation (Seq Scan, Index Scan, etc.)
CostEstimated startup..total cost
RowsEstimated rows (vs actual with ANALYZE)
WidthAverage row width in bytes
TimeActual execution time (ANALYZE only)
LoopsNumber of times node was executed

Color Coding

Nodes are color-coded by type:

  • 🔵 Scans: Seq Scan, Index Scan, Bitmap Scan
  • 🟢 Joins: Nested Loop, Hash Join, Merge Join
  • 🟡 Sorts: Sort, Incremental Sort
  • 🟣 Aggregates: Aggregate, GroupAggregate, HashAggregate

Understanding Plans

Common Node Types

NodeDescriptionPerformance
Seq ScanFull table scanSlow on large tables
Index ScanUses indexFast for selective queries
Index Only ScanUses covering indexVery fast
Bitmap ScanTwo-phase index scanGood for medium selectivity
Hash JoinHash-based joinFast for large joins
Nested LoopRow-by-row joinFast for small sets

Performance Warnings

Watch for:

  • High row estimates with low actual rows (bad statistics)
  • Sequential scans on large tables
  • Sort operations without indexes
  • High loop counts in nested loops

Optimization Tips

  1. Add indexes for columns in WHERE clauses
  2. Update statistics with ANALYZE table_name
  3. Check for missing indexes on join columns
  4. Consider partial indexes for filtered queries
  5. Use LIMIT when possible

On this page