How to Read a SQL Server Execution Plan: Seeks, Scans, and Key Lookups

Written by

in

How to Read a SQL Server Execution Plan: Seeks, Scans, and Key Lookups

The last two lessons referenced execution plans repeatedly to prove their claims. Here’s how to actually read one systematically — the skill that turns “this query feels slow” into “this specific operator is the problem, for this specific reason.”

Reading an execution plan(right to left, top to bottom)data flows this direction as you read →Index Seekcustomer_id = 42① runs first — good!Key Lookupjumps back, per row!② the expensive partSELECT resultrows you see③ you read this lastthe #1 diagnostic signal — estimated vs actual rows:Estimated: 12Actual: 45,000huge gap = stale statsor a bad estimate! ⚠cost % is built onthe SAME estimate —a 5% operator can bethe real bottleneck 📌

In SSMS, press Ctrl+M (Include Actual Execution Plan) before running a query.

SET STATISTICS IO ON;
SET STATISTICS TIME ON;

SELECT customer_id, order_status, order_total
FROM dbo.OrderLog
WHERE customer_id = 42;

The Key Plan Elements

Plan element What it means
Index Seek Good — navigated the B-tree directly to matching rows, exactly the root→branch→leaf path from Lesson 1
Index Scan Read the entire index — fine on small tables, a red flag on huge ones for selective queries
Table Scan No usable index existed at all — the engine has no B-tree to navigate
Key Lookup Jump back to the clustered index per row — the exact problem Lesson 2’s covering index (INCLUDE) fixes

Read a plan right to left, top to bottom — the rightmost, deepest operators run first (typically the actual table/index access), feeding data up and left into operators that filter, join, and aggregate it, until the leftmost operator produces the final result.

The Single Most Useful Diagnostic Signal

A large gap between Estimated and Actual rows means stale statistics, or a shape defeating good estimation

The optimizer chooses its plan based on estimated row counts — when those estimates are badly wrong, it often picks a suboptimal plan (the wrong join type, an index skipped in favor of a scan, an inappropriate memory grant). STATISTICS IO reports logical reads per table, often a more stable, comparable metric across runs than wall-clock time, since wall-clock time is affected by whatever else the machine happens to be doing at that moment.

The Cost Percentage Trap

Common mistake: Treating an operator’s cost percentage (the big bold number SSMS shows under each operator) as a reliable measure of real-world expense. It’s derived from the same potentially-wrong estimates driving the whole plan — an operator estimated at 5% of a query’s cost can be the actual bottleneck if its underlying row estimate was badly off. Cross-check cost percentage against actual row counts (visible by hovering over each operator) before trusting it.
-- A parameter-sniffing-prone query worth trying: run once with a common value,
-- once with a rare one, and compare estimated vs actual rows on the same plan shape
SELECT * FROM dbo.OrderLog WHERE order_status = 'completed'; -- common
SELECT * FROM dbo.OrderLog WHERE order_status = 'cancelled'; -- rare
-- Different row counts naturally produce different (correct) estimates per query --
-- this becomes a real problem specifically inside a cached stored procedure plan,
-- covered in the Performance Tuning course
Practice tip: Run a query you already know is slow (or deliberately write one against a large table with no useful index), capture its actual execution plan, and walk it right to left identifying every Scan, Seek, and Lookup by name before looking at cost percentages at all. Building that habit — identify operators first, judge cost second — avoids the trap above.

Enjoyed this?

Subscribe to get every new SQL Server lesson as soon as it’s published, and share it with a developer who’d find it useful.

📡 Subscribe via RSS  | 
Share on X  | 
Share on LinkedIn  | 
Share on Facebook

Want the full structured course with quizzes, projects, and 10+ exercises per chapter? Check out SQL Server for Developers & DBAs, coming soon on this site.