At this point, you might have a totally reasonable question: why do we need two different tools for analysis? Which one do people use more: EXPLAIN ANALYZE or pg_stat_statements? Let’s break down these two approaches, their strengths and weaknesses, and where and when each one is used.
Problems These Tools Solve
EXPLAIN ANALYZE: this is your deep-dive tool for a single specific query. If you’re curious about how PostgreSQL runs a query, what nodes it uses, how many rows get processed, and how long each operation takes, this is your go-to. It helps answer the question: “Why is my specific query running slow?”
pg_stat_statements: this is your high-level monitoring tool, giving you info about the performance of all queries running in your database. This is your pick if you want the big picture: “Which queries in my database are the slowest?” or “Which queries are putting the most load on my server?”
When to Use EXPLAIN ANALYZE
EXPLAIN ANALYZE is your debugging tool that lets you see how PostgreSQL executes a specific query. Use it in these scenarios:
Pinpoint Query Optimization If you get a complaint that your app page is taking forever to load, the first thing you’ll do is find the query causing the problem and run EXPLAIN ANALYZE on it. This will show you the query execution plan and real metrics like execution time and number of rows processed.
Choosing the Right Index When you create a new index or change an existing one, use EXPLAIN ANALYZE to see if PostgreSQL actually picks that index for the job. If not, maybe you made an index that doesn’t really help optimize your queries.
Debugging Complex Queries If you’re writing a gnarly query with lots of JOINs or WHEREs, analyzing the real execution plan with EXPLAIN ANALYZE will help you spot bottlenecks, like unnecessary sequential scans (hey there, Seq Scan).
Example: Optimizing a Query with EXPLAIN ANALYZE
-- Query that runs slow
SELECT *
FROM students
WHERE name = 'Alice';
-- Analyze the execution plan
EXPLAIN ANALYZE
SELECT *
FROM students
WHERE name = 'Alice';
If you see a Seq Scan being used, you probably forgot to create an index:
-- Create an index on the name column
CREATE INDEX idx_students_name ON students(name);
-- Check again
EXPLAIN ANALYZE
SELECT *
FROM students
WHERE name = 'Alice';
When to Use pg_stat_statements
This tool is a must-have for analyzing the performance of your whole system. Use it in these scenarios:
Production Monitoring pg_stat_statements shows query execution stats over a certain period. You can easily find the slowest queries thanks to the total_time column, which shows the total execution time for each query.
Finding “Heavy” Queries Want to know which queries are putting the most load on your database? Sort queries by memory reads (shared_blks_hit) or by the number of rows processed (rows).
Spotting High-Frequency Queries Sometimes it’s not just the long-running queries that cause trouble, but also the ones that run super often. For example, if a query runs 100 times a minute, even a tiny optimization can seriously cut down server load.
Example: Finding Slow Queries with pg_stat_statements
-- View query stats
SELECT query,
calls,
total_time,
rows
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 5;
This query will show you the top 5 queries that eat up the most time.
Comparing the Approaches: What’s the Difference?
| Criteria | EXPLAIN ANALYZE | pg_stat_statements |
|---|---|---|
| Analysis Focus | One specific query | Global monitoring of all queries |
| Level of Detail | Actual data for each plan node | Summary stats for each query |
| Context | Used during development | Used in production environment |
| Execution Requirement | Executes the query and measures its time | Doesn’t execute queries, just aggregates data |
| Setup Simplicity | No setup needed | Requires extension installation |
| Resource Usage | One-time measurement | Ongoing stats collection depends on load |
Using Both Tools Together
Like everything in programming, there’s no magic button that fixes everything. The best approach is to use both tools together. For example:
Use
pg_stat_statementsto spot the slowest or most frequent queries in your system.Then dig into those queries with
EXPLAIN ANALYZEto figure out why they’re problematic.
Practical Example: A Comprehensive Approach
-- Step 1: Find the slowest query
SELECT query, total_time, calls
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 1;
-- Step 2: Analyze this query
EXPLAIN ANALYZE
<copy the query from the previous step>;
Common Mistakes When Using These Tools
When working with EXPLAIN ANALYZE and pg_stat_statements, there are a few mistakes beginners often make:
Forgetting about data relevance. If you analyze a query on an empty table, the
EXPLAIN ANALYZEoutput can be misleading. Make sure your test database reflects real data volumes.Ignoring the resource cost of monitoring. If you have the
pg_stat_statementsextension enabled on your production server, make sure it’s tuned right and not causing extra load.Reading the theoretical plan instead of the real one. Remember, plain
EXPLAINonly gives you the theoretical query plan. UseEXPLAIN ANALYZEto get real data.
Now you’re armed with all the knowledge you need to not just fight slow queries, but actually prevent them from popping up. PostgreSQL gives you powerful tools, and using them together smartly lets you get the best performance even on heavy systems.
GO TO FULL VERSION