SQL Server Execution Plan Operators: Costing, Plan Shape, and What to Ignore

SQL Server Execution Plan Operators: Costing, Plan Shape, and What to Ignore

You’ve seen individual operators already (Seek, Scan, Key Lookup). Now let’s read a whole plan the way someone diagnosing a real incident actually does.

Execution Plans, sketched out(cost % is an estimate — verify against actual rows)Index SeekCustomer.PKcost: 2%50 rowsKey LookupOrderLog clustered indexcost: 91%!480,000 rows!Nested LoopJoin (root)cost: 5%The gap that actually matters:Estimated: 50 rowspredicted when the plan compiled(shown in the plan, not measured)vsActual: 480,000 rowswhat really came back9,600x gap — the real signalHigh cost % is a fine place to start —but it’s estimate-based. Check actualrows before trusting it. 📌

Cost Percentages: Useful, But Not the Whole Story

Cost % is an ESTIMATE-based number, computed pre-execution it can be badly wrong when estimates are wrong (see Module 3)

The operator showing “87% cost” is a reasonable place to start looking — but it’s computed from the optimizer’s row estimates, which you now know can be badly wrong under parameter sniffing or stale statistics. Cross-check cost % against actual row counts, not just at face value.

Reading Plan Shape, Not Just Individual Icons

  • Thick arrows between operators represent many rows flowing — trace these back to find where row counts balloon unexpectedly
  • Warning icons (yellow triangle) flag things like implicit conversions or missing statistics directly in the plan — don’t skip past these
  • Parallelism icons (yellow circle with arrows) show where the plan split across threads — useful context, not automatically good or bad

Estimated vs Actual: The Signal That Matters Most

-- Always use ACTUAL execution plan (Ctrl+M), not estimated — estimated never shows real row counts
SELECT * FROM dbo.OrderLog WHERE customer_id = 42;

Hover any operator and compare Estimated Number of Rows to Actual Number of Rows. A 10x+ gap anywhere in the plan is the single strongest signal something upstream (stale stats, a non-SARGable predicate, parameter sniffing) is misleading the optimizer — often more informative than the cost percentage itself.


Enjoyed this?

Subscribe to get every new 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 and hands-on labs? Check out SQL Server Performance Tuning, coming soon on this site.