Advanced SQL & Data Engineering • Training 06
Article-Training • SQL Server–Friendly Series

Execution Plans

Find Where the Query Hurts — and Why

Execution plans show how SQL Server actually chose to execute your query.

Query → Optimizer Choice → Operators → Row Flow → Cost / Reads / Time → Fix
Scan
→
Filter
→
Join
Sort
→
Aggregate
→
Result
8learning modules
24interactive practices
5rapid review questions
50%certificate threshold
Learning target
Read SQL Server execution plans as a row-flow story and identify where query work is really happening.
Practice progress0 / 24

Complete 12 of 24 practices (50%) and enter your name to unlock the Certificate of Participation.

MODULE 01
🧠

Read the Plan as a Story, Not a Poster

An execution plan is a data-flow story. Operators consume rows, transform them and pass them onward. Read the plan to understand the path from access method to joins, sorts, aggregates and final output.

🔍
Follow the rows

Instead of asking 'Which icon is bad?', ask: 'Where did the row count explode? Where did SQL Server scan more than expected? Where did it sort or spool because the chosen shape demanded it?'

Core ideas

  • Operators consume and emit rows
  • The plan shape reflects optimizer choices
  • One operator rarely explains the whole problem
  • Read row flow before chasing icons
Baseline diagnostic session
SET STATISTICS IO ON;
SET STATISTICS TIME ON;

SELECT ...
FROM ...
WHERE ...;

-- Include Actual Execution Plan in SSMS.
-- Compare plan shape + logical reads + elapsed time.
✅

Execution plans become useful when you connect the picture to rows, reads, time and business intent.

Practice — 3 cases

Practice 1 / Práctica 1
What is the main purpose of an execution plan?
Practice 2 / Práctica 2
What is the biggest mistake when first learning execution plans?
Practice 3 / Práctica 3
What should you ask first when reading a plan?
MODULE 02
📏

Estimated vs Actual Rows: The Cardinality Story

The optimizer chooses a plan before the query runs, so it must estimate how many rows each operator will process. When those estimates are wrong, the chosen join type, memory grant or access method may also be wrong.

🔍
Bad estimates create bad downstream choices

If SQL Server expects 10 rows but receives 10 million, a nested loops plan that looked cheap on paper may become painfully expensive at runtime.

Core ideas

  • Estimated Rows = optimizer prediction
  • Actual Rows = runtime reality
  • Large differences deserve investigation
  • Statistics and predicate shape strongly influence estimates
What to compare
-- In the Actual Execution Plan, inspect:
Estimated Number of Rows
Actual Number of Rows
Actual Number of Rows for All Executions
Estimated Number of Executions
Actual Number of Executions

-- Large gaps often matter more
-- than the operator icon itself.
✅

A plan problem is often an estimation problem before it becomes an operator problem.

Practice — 3 cases

Practice 4 / Práctica 4
What is the difference between an estimated plan and an actual plan?
Practice 5 / Práctica 5
Why are actual row counts valuable?
Practice 6 / Práctica 6
What can a large estimate-vs-actual difference indicate?
MODULE 03
🔎

Scans, Seeks and the Myth of the Bad Scan

A scan is not automatically a problem, and a seek is not automatically good. The right access method depends on selectivity, table size, row goals, covering columns and how many rows the rest of the plan needs.

🔍
Read the amount of work, not the label

A scan over 20 rows may be cheaper than a seek plus thousands of key lookups. A seek over half the table can still be expensive.

Core ideas

  • Scans can be correct for broad retrieval
  • Seeks are strongest when predicates are selective and searchable
  • Logical reads tell you how much page work occurred
  • Look at the whole access pattern, including lookups
Selective vs broad access
-- Selective predicate may favor a seek:
SELECT *
FROM dbo.Orders
WHERE CustomerID = 12345;

-- Broad predicate may reasonably favor a scan:
SELECT *
FROM dbo.Orders
WHERE OrderDate >= '2020-01-01';

-- Validate with actual reads and row counts.
✅

The goal is not 'make every scan a seek'; the goal is 'make the access method fit the amount of data required.'

Practice — 3 cases

Practice 7 / Práctica 7
Is an Index Scan automatically bad?
Practice 8 / Práctica 8
What does an Index Seek generally mean?
Practice 9 / Práctica 9
What should you compare before replacing a scan with an index?
MODULE 04
🔗

Join Operators: Loops, Hash and Merge

SQL Server chooses physical join algorithms based on estimated row counts, available order, indexes and cost. A join operator is not good or bad by itself; it is good or bad for the row volumes and access paths around it.

🔍
The same logical JOIN can have very different physical plans

An INNER JOIN in SQL text could become Nested Loops, Hash Match or Merge Join. The optimizer chooses based on its estimate of the cheapest physical strategy.

Core ideas

  • Nested Loops often fits small outer inputs with efficient inner access
  • Hash Match often fits large unsorted equality joins
  • Merge Join benefits from ordered inputs
  • Wrong cardinality estimates can lead to the wrong join algorithm
Same logical join, different physical possibilities
SELECT o.OrderID,
       c.CustomerName
FROM dbo.Orders AS o
JOIN dbo.Customers AS c
  ON c.CustomerID = o.CustomerID;

-- Physical operator could be:
-- Nested Loops
-- Hash Match
-- Merge Join

-- Inspect row estimates and indexes.
✅

Do not tune by forcing a join type first; understand why the optimizer chose it and whether the surrounding estimates were correct.

Practice — 3 cases

Practice 10 / Práctica 10
When are Nested Loops joins often effective?
Practice 11 / Práctica 11
When is a Hash Match join often a reasonable choice?
Practice 12 / Práctica 12
What does a Merge Join generally need?
MODULE 05
📚

Key Lookups, Covering Indexes and Hidden Multiplication

A Key Lookup is not automatically bad. It becomes suspicious when a nonclustered seek returns many rows and SQL Server must perform a lookup for each one to retrieve missing columns.

🔍
One cheap lookup × 100,000 rows is no longer cheap

The operator tooltip may look inexpensive per execution, but repeated executions can dominate logical reads and elapsed time.

Core ideas

  • Look at Actual Number of Executions
  • Check how many rows trigger the lookup
  • Consider INCLUDE columns only after measuring benefit
  • Remember that wider indexes increase storage and write cost
Covering concept
-- Existing index:
CREATE INDEX IX_Orders_CustomerID
ON dbo.Orders(CustomerID);

-- Query also needs OrderDate and Amount.
-- Possible covering version:
CREATE INDEX IX_Orders_CustomerID
ON dbo.Orders(CustomerID)
INCLUDE (OrderDate, Amount);

-- Validate reads before and after.
✅

A covering index is a tradeoff, not a trophy: remove expensive lookups only when the workload justifies the extra index width.

Practice — 3 cases

Practice 13 / Práctica 13
What does a Key Lookup usually indicate?
Practice 14 / Práctica 14
Why can a Key Lookup become expensive?
Practice 15 / Práctica 15
What is one possible fix for an expensive repeated lookup?
MODULE 06
💾

Sorts, Hashes, Memory Grants and tempdb Spills

Some operators need workspace memory before they run. SQL Server grants memory based on estimates. If the grant is too small, Sort or Hash operators may spill to tempdb. If it is far too large, one query can reserve memory that other queries need.

🔍
Memory problems often begin as estimate problems

A plan estimated for 5,000 rows may receive 5 million rows. The Sort now needs far more memory than the optimizer granted, so intermediate runs spill to tempdb.

Core ideas

  • Sort and Hash can request significant workspace memory
  • Spill warnings deserve investigation
  • Fix the cause before blindly increasing resources
  • Estimates, row width and useful ordering all influence memory needs
What to inspect
-- In the Actual Plan inspect:
Memory Grant Info
Warnings
Spill Level
Actual Rebinds / Rewinds
Actual Rows
Estimated Rows

-- Also measure:
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
✅

A spill is evidence of extra work; the real tuning question is why the operator needed more memory than SQL Server expected.

Practice — 3 cases

Practice 16 / Práctica 16
What does a Sort operator need in order to perform well?
Practice 17 / Práctica 17
What is a spill to tempdb?
Practice 18 / Práctica 18
What can cause a bad memory grant?
MODULE 07
⚠️

Spools, Warnings and Operators That Deserve a Second Look

Some plan operators exist because the optimizer is protecting itself from repeated work or preserving correctness. Spools, exchanges and warning icons are clues, not automatic proof of a bad plan.

🔍
Treat unusual operators as questions, not verdicts

A spool may be saving the query from rescanning an expensive subtree. But if a huge spool is built repeatedly, the underlying join or predicate design may deserve attention.

Core ideas

  • Spools cache intermediate rows within the plan
  • Warnings can reveal spills or conversions
  • Parallel exchanges show row movement across threads
  • Investigate context before removing an operator
Common clues to inspect
Plan clues:
- Table Spool / Index Spool
- Sort / Hash spill warning
- Implicit conversion warning
- Missing join predicate warning
- Large row-estimate mismatch
- Huge Actual Number of Executions
- Unexpected parallel exchanges

Clue != root cause.
Trace the row flow.
✅

The plan is evidence. Tune the reason the operator exists, not the icon itself.

Practice — 3 cases

Practice 19 / Práctica 19
What does a Spool generally do?
Practice 20 / Práctica 20
Is a Spool automatically bad?
Practice 21 / Práctica 21
What can a warning icon or plan warning indicate?
MODULE 08
🏭

Production Tuning Workflow: Measure → Explain → Change → Verify

The execution plan is a diagnostic tool, not the finish line. A disciplined tuning workflow begins with a baseline, explains where work is happening, changes one thing at a time, and verifies improvement under representative conditions.

🔍
Tune by evidence, not by icon anxiety

A plan with a scan may be excellent. A plan full of seeks may still be terrible. The proof is in reads, CPU, elapsed time, row counts and correctness.

Core ideas

  • Capture a baseline before changing anything
  • Focus on row-flow problems and estimate errors
  • Make one targeted change at a time
  • Verify improvement with actual runtime evidence
Production checklist
1. Reproduce the slow query safely
2. Capture Actual Execution Plan
3. Record STATISTICS IO / TIME
4. Find large row-estimate gaps
5. Inspect access methods and joins
6. Look for repeated lookups / spills / warnings
7. Form a root-cause hypothesis
8. Make one targeted change
9. Re-run under comparable conditions
10. Confirm result correctness
11. Keep the change only if the evidence improves
✅

The best execution-plan skill is not recognizing icons; it is building and testing a correct explanation of where the work comes from.

Practice — 3 cases

Practice 22 / Práctica 22
What is the best way to validate a tuning change?
Practice 23 / Práctica 23
What is a strong first tuning sequence?
Practice 24 / Práctica 24
What is the strongest production rule for execution plans?
5-Question Knowledge Check

Can you diagnose a SQL Server plan without chasing icons?

Open each item after answering it in your own words. The 24 interactive practices above drive certificate progress.

1. What is the first thing to understand in an execution plan?

The row-flow story: where rows come from, how many are expected and actual, how they are transformed, and where work multiplies.

2. Why do estimate errors matter?

Because the optimizer chooses joins, memory grants and access methods using estimated cardinality.

3. Is a scan automatically bad?

No. A scan can be the cheapest strategy when many rows are needed or the object is small.

4. What can make a Key Lookup expensive?

A lookup may execute once per qualifying row, multiplying access work.

5. How do you prove a tuning change helped?

Compare runtime evidence and correctness before and after under comparable conditions.

Execution Plan Diagnostic Map

A practical reading sequence

QuestionWhat to inspect
Did SQL Server estimate correctly?Estimated Rows vs Actual Rows
How much data was read?STATISTICS IO + access operators
Did work multiply?Actual Executions + join row flow
Was extra workspace needed?Sort / Hash / memory grants / spills
Did the fix really help?Before/after reads, time, CPU and correctness

Certificate of Participation

Complete at least 12 of the 24 practice cases (50%) and enter your name.

0 / 24 • 0%
Production note

Execution plans are diagnostic evidence, not a scorecard.