0Pricing
SQL Interview Prep · Lesson

Reading an EXPLAIN Plan

Interpreting scan types, join methods, and cost estimates in a query plan.

Reading an EXPLAIN Plan is a free SQL Interview Prep lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the SQL Interview Prep learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Interviewers Ask About EXPLAIN

Once you reach a senior screen, interviewers stop asking write a query and start asking why is this query slow. The tool that answers that is EXPLAIN.

EXPLAIN shows the database's execution plan: the step-by-step strategy the planner chose to run your SQL. It reveals which tables are scanned, in what order they are joined, and roughly how expensive each step is.

Being able to read a plan signals that you understand the engine, not just the syntax. That is exactly the line interviewers use to separate mid-level from senior.

EXPLAIN vs EXPLAIN ANALYZE

There are two flavors and interviewers love the distinction.

  • EXPLAIN shows the planner's estimated plan without running the query. Fast and safe.
  • EXPLAIN ANALYZE actually executes the query and reports the real row counts and timings alongside the estimates.

The gold mine is comparing estimated rows to actual rows. A big mismatch means the planner has bad statistics and is likely making a poor choice.

Caution: EXPLAIN ANALYZE runs the query for real, so it will perform any INSERT or UPDATE unless wrapped in a rolled-back transaction.

EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 42;

How to Read the Tree

A plan is a tree, not a list. The most indented nodes are the leaves that run first; results flow upward to the root, which produces the final output.

Read it inside-out: find the deepest node, that is where execution begins. Each parent consumes the rows its children emit.

In an interview, narrate it that way: first we scan this table, those rows feed into this join, the join feeds into the sort, the sort feeds the limit. That bottom-up narration is what they want to hear.

Anatomy of a Plan Node

Every node in a Postgres plan carries the same key numbers:

  • cost=0.00..35.50 startup cost..total cost in arbitrary planner units
  • rows=1000 estimated number of rows produced
  • width=64 estimated average row size in bytes

The first cost is the startup cost (work before the first row appears, like building a hash table). The second is the total cost to return all rows. Higher total cost is the planner's guess at relative expense.

Seq Scan on orders  (cost=0.00..35.50 rows=1000 width=64)

A Worked Example

Consider a simple filtered query. The plan below tells a story in one line.

It is a Seq Scan (full table read) on orders, applying the filter status = 'shipped'. The planner estimates 1000 matching rows.

If orders has 10 million rows and only 1000 match, an interviewer expects you to say: a sequential scan here is wasteful, an index on status (or on a more selective column) would let us avoid reading the whole table.

EXPLAIN SELECT * FROM orders WHERE status = 'shipped';

Seq Scan on orders  (cost=0.00..18334.00 rows=1000 width=64)
  Filter: (status = 'shipped'::text)

Estimated vs Actual Rows

With EXPLAIN ANALYZE you also get actual numbers in parentheses.

Look at the example: the planner estimated 1000 rows but actually got 480000. That is a 480x underestimate. The planner picked its strategy assuming few rows, so its choice is probably wrong for the real data.

In interviews, this gap is your headline diagnosis: the statistics are stale, run ANALYZE on the table, then the planner will likely pick a better plan.

Seq Scan on orders
  (cost=0.00..18334.00 rows=1000 width=64)
  (actual time=0.02..210.4 rows=480000 loops=1)

What loops=N Means

The loops value matters more than candidates expect. It is the number of times a node was executed.

This appears on the inner side of a nested loop join: the inner node runs once per outer row. If loops=480000, that inner step executed 480 thousand times.

Important: the per-row time and row count shown are per loop. To get the true total you multiply by loops. A node that looks cheap at 0.004ms per loop becomes nearly 2 seconds across 480000 loops.

Index Scan using idx_cust on orders
  (actual time=0.003..0.004 rows=1 loops=480000)

Cost Is Relative, Not Milliseconds

A frequent trap: candidates read cost=18334 and say that takes 18 seconds. Wrong.

Cost is in arbitrary planner units, calibrated so that one sequential page read equals 1.0. It is only meaningful for comparing plans against each other, not as a wall-clock figure.

For real timing you need EXPLAIN ANALYZE and its actual time values, measured in milliseconds. Say this clearly in an interview; it shows you actually understand the metric.

Reading a Join Plan

Here is a two-table plan. Read it bottom-up.

First two scans gather rows from orders and customers. They feed a Hash Join: one side is hashed, the other side probes the hash. The join's output then feeds the final result.

Notice the indentation shows the structure: both scans sit under the Hash Join. The interviewer wants you to identify the join method (hash here) and which table is being hashed (usually the smaller one).

Hash Join  (cost=30.0..520.0 rows=900 width=72)
  Hash Cond: (o.customer_id = c.id)
  ->  Seq Scan on orders o  (cost=0..400 rows=10000)
  ->  Hash  (cost=18..18 rows=500)
        ->  Seq Scan on customers c  (cost=0..18 rows=500)

Red Flags to Call Out

Train your eye for these warning signs in any plan:

  • Seq Scan on a huge table with a selective filter, an index could help.
  • Estimated rows far from actual, stale statistics.
  • Nested Loop with high loops over a big table, often a missing index on the inner join key.
  • Sort or Hash spilling to disk (shown as Disk usage), work_mem is too small.
  • Rows Removed by Filter very high, you read and discarded most of the table.

Output Formats and BUFFERS

Plans come in several formats. The default TEXT is what you read aloud in interviews. But you can also request structured output.

EXPLAIN (FORMAT JSON) or FORMAT YAML produces machine-readable plans that tools and dashboards parse. You rarely need them by hand, but knowing they exist is a nice senior touch.

Add options in parentheses: EXPLAIN (ANALYZE, BUFFERS). The BUFFERS option reports cache hits versus disk reads, which is gold for diagnosing I/O-bound queries.

EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM orders WHERE customer_id = 42;

Quick Check

An interviewer shows you an EXPLAIN ANALYZE node with rows=1000 in the cost section but actual ... rows=480000. What is the most likely diagnosis?

Recap

You can now read a plan like a senior:

  • EXPLAIN estimates, EXPLAIN ANALYZE runs and measures.
  • Read the tree bottom-up; leaves run first, root produces output.
  • Each node shows cost (relative units), rows, and width; actual time is the real millisecond figure.
  • loops multiplies per-loop numbers, watch nested loops.
  • The estimated-vs-actual row gap is your top diagnostic signal.

Narrate the plan aloud and call out red flags, that is the interview-winning behavior.

Frequently asked questions

Is the “Reading an EXPLAIN Plan” lesson free?

Yes — the full text of “Reading an EXPLAIN Plan” is free to read here on the web, and the SQL Interview Prep course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the SQL Interview Prep course, upgrade to CoddyKit PRO.

What will I learn in “Reading an EXPLAIN Plan”?

Interpreting scan types, join methods, and cost estimates in a query plan. You practise SQL Interview Prep with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start SQL Interview Prep?

No prior experience is required. SQL Interview Prep on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Reading an EXPLAIN Plan” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this SQL Interview Prep lesson?

Yes. Every SQL Interview Prep lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Reading an EXPLAIN Plan
  2. Seq Scan vs Index Scan vs Index-Only
  3. Join Algorithms: Nested Loop, Hash, Merge
  4. Spotting and Fixing Slow Queries
← Back to SQL Interview Prep