🚀
Dev Blogs
How to Analyze and Optimize PostgreSQL Query Cost Using EXPLAIN (pgAdmin + Dalibo)
•6m•Rasika Lakmal

How to Analyze and Optimize PostgreSQL Query Cost Using EXPLAIN (pgAdmin + Dalibo)

Master PostgreSQL performance tuning by learning how to analyze and optimize query costs using pgAdmin's EXPLAIN and visualizing execution plans with Dalibo Explain.

How to Analyze and Optimize PostgreSQL Query Cost Using EXPLAIN (pgAdmin + Dalibo)

When working with PostgreSQL, slow queries are common. The real skill is understanding why a query is slow and how to fix it.

In this guide, you’ll learn how to:

  • Use pgAdmin’s EXPLAIN.
  • Visualize queries using Dalibo Explain.
  • Understand query cost components.
  • Identify and optimize expensive queries.

1. What is EXPLAIN in PostgreSQL?

PostgreSQL provides the EXPLAIN command to show the planner’s estimated execution plan for a query. It does not run the query by default, and the output includes estimates such as cost, row counts, join strategies, scan types, and index usage.

Example:

EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';

2. Running EXPLAIN in pgAdmin

Using pgAdmin:

Steps:

  1. Open Query Tool.
  2. Write your query.
  3. Click Explain instead of Run.

You may see output like:

Seq Scan on users  (cost=0.00..431.00 rows=21000 width=64)

3. Understanding Query Cost

PostgreSQL uses cost units, not actual time. The format is:

(cost=startup_cost..total_cost)

Example: (cost=0.00..431.00)

Meaning:

  • Startup cost: estimated work before the first row can be returned.
  • Total cost: estimated work to produce all rows from that node.

Deep Dive: What influences cost?

PostgreSQL cost is influenced by configuration parameters that model disk I/O and CPU work, such as:

  • seq_page_cost: Estimated cost of a sequential disk page fetch.
  • cpu_tuple_cost: Estimated cost of processing each row (tuple).

👉 Higher estimated cost generally means a more expensive plan, but the number is relative rather than an absolute time measurement.

4. What Makes a Query Expensive?

Here are common red flags:

  • Sequential scan on a large table.
  • Nested loop join over many rows.
  • Large mismatch between estimated and actual row counts.
  • High total cost compared with similar queries.

A sequential scan is not always bad; it can be the cheapest choice for small tables or when a large portion of the table must be read. Index scans are often better for selective lookups, while hash joins and merge joins can be better for larger joins depending on indexes and data shape.

5. Visualizing with Dalibo Explain

Raw EXPLAIN output can be hard to read. Dalibo Explain is a PostgreSQL execution plan visualizer that helps analyze and share plans.

Tool:

https://explain.dalibo.com/

The tool recommends using:

EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON)
SELECT * FROM users WHERE email = 'test@example.com';

Why these options?

  • FORMAT JSON: Usually has better support in Dalibo Explain for interactive visualization.
  • BUFFERS: Shows how many shared buffers were hit vs. read from disk, helping you understand whether your query is I/O bound.

6. EXPLAIN vs EXPLAIN ANALYZE

CommandWhat it does
EXPLAINShows the estimated plan only
EXPLAIN ANALYZEActually runs the query and reports real execution data

Example:

EXPLAIN ANALYZE SELECT * FROM users;

This shows actual execution time, actual row counts, and how close the estimates were to reality.

7. How to Identify Expensive Queries

Look for these signals:

  • High estimated total cost relative to similar queries.
  • Large row estimates.
  • Sequential scans on large tables.
  • Big differences between estimated and actual rows.

Why do estimates go wrong?

Estimation errors often happen due to:

  • Outdated statistics: The planner doesn't know the current state of the table.
  • Data skew: Uneven distribution of data.
  • Correlated columns: When columns are related but PostgreSQL assumes they are independent.

For example, if PostgreSQL estimates 10 rows but the plan actually returns 10,000, that can suggest weak statistics.

8. Practical Optimization Tips

  • ✅ Add indexes where they match real query patterns.
    CREATE INDEX idx_users_email ON users(email);
    

Comparison: Before vs. After Index

ScenarioPlan TypeNote
Before IndexSeq Scan on usersCommon when no useful index exists
After IndexIndex Scan using idx_users_emailOften better for selective lookups
  • ✅ Avoid SELECT * when you only need a few columns.
  • ✅ Use selective WHERE clauses.
  • ✅ Refresh statistics when data changes significantly.
    ANALYZE users;
    
  • ✅ Watch for N+1 queries and inefficient joins.

9. Real-World Backend Insight

If you are building APIs with Node.js or NestJS, slow queries often become slow endpoints. Query tuning is usually more effective than prematurely optimizing application code.

10. Recommended Workflow

  1. Write the query.
  2. Run EXPLAIN in pgAdmin.
  3. Compare estimated vs actual behavior with EXPLAIN ANALYZE.
  4. Paste the JSON plan into Dalibo Explain.
  5. Identify bottlenecks.
  6. Optimize with indexes, joins, filters, or updated statistics.

Conclusion

Understanding PostgreSQL query cost is essential for backend performance. pgAdmin and Dalibo Explain make it easier to spot slow plans, interpret execution behavior, and optimize with confidence.

Pro tip: Don’t guess performance — measure it with EXPLAIN ANALYZE.