An execution plan shows exactly how SQL Server processes your query: which indexes it uses, how it joins tables, and where it spends the most resources. Understanding execution plans is the most important skill for query performance tuning. SQL Server provides both estimated and actual execution plans.
Viewing Execution Plans
You can view execution plans in SSMS by clicking "Display Estimated Execution Plan" (Ctrl+L) or "Include Actual Execution Plan" (Ctrl+M) before running a query. In T-SQL, you can enable text-based plans.
-- Show estimated plan as text
SET SHOWPLAN_TEXT ON;
GO
SELECT * FROM Orders WHERE CustomerID = 42;
GO
SET SHOWPLAN_TEXT OFF;
GO
-- Show actual execution statistics
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SELECT o.OrderID, c.CustomerName
FROM Orders o
INNER JOIN Customers c ON o.CustomerID = c.CustomerID
WHERE o.OrderDate >= '2024-01-01';
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;Key Plan Operators
Execution plans consist of operators (nodes) that each perform a specific operation. Understanding the most common operators helps you quickly diagnose issues.
-- Common operators and what they mean:
--
-- Table Scan: Reads every row. Indicates a missing index.
-- Clustered Index Scan: Reads the entire clustered index.
-- Index Seek: Efficiently jumps to matching rows. This is ideal.
-- Key Lookup: After an index seek, fetches remaining columns
-- from the clustered index. Consider a covering index.
-- Nested Loops: Joins each row from outer input with inner input.
-- Efficient for small datasets.
-- Hash Match: Builds a hash table for joining. Good for large,
-- unsorted datasets.
-- Sort: Sorts rows, can be expensive. Check if an index
-- can provide pre-sorted data.Identifying Table Scans
A Table Scan or Clustered Index Scan means SQL Server is reading every row. For large tables, this is a red flag. Adding an index on the filtered column converts the scan to a seek.
-- This query likely causes a scan if Email is not indexed
SELECT * FROM Users WHERE Email = 'user@example.com';
-- Fix: create an index
CREATE NONCLUSTERED INDEX IX_Users_Email ON Users (Email);
-- Now the plan shows an Index Seek instead of a scanMissing Index Recommendations
SQL Server sometimes includes missing index suggestions in execution plans. You can also query the DMVs for accumulated missing index recommendations.
SELECT
OBJECT_NAME(d.object_id) AS TableName,
d.equality_columns,
d.inequality_columns,
d.included_columns,
s.user_seeks,
s.avg_total_user_cost * s.avg_user_impact * (s.user_seeks + s.user_scans) AS ImpactScore
FROM sys.dm_db_missing_index_details d
INNER JOIN sys.dm_db_missing_index_groups g
ON d.index_handle = g.index_handle
INNER JOIN sys.dm_db_missing_index_group_stats s
ON g.index_group_handle = s.group_handle
ORDER BY ImpactScore DESC;Eliminating Key Lookups
A Key Lookup happens when an index seek finds matching rows but needs additional columns from the clustered index. Adding those columns to the index with INCLUDE eliminates the lookup.
-- This query seeks on Department but needs FirstName and Salary
SELECT FirstName, Salary FROM Employees WHERE Department = 'Sales';
-- Without INCLUDE: Index Seek + Key Lookup
CREATE INDEX IX_Dept ON Employees (Department);
-- With INCLUDE: Index Seek only (covering index)
CREATE INDEX IX_Dept_Cover ON Employees (Department)
INCLUDE (FirstName, Salary);Comparing Estimated vs Actual Rows
Large discrepancies between estimated and actual row counts indicate stale statistics. When the optimizer underestimates rows, it may choose inefficient plans. Updating statistics often resolves this.
-- Update statistics for a specific table
UPDATE STATISTICS Orders;
-- Update with full scan for most accurate stats
UPDATE STATISTICS Orders WITH FULLSCAN;
-- Update all statistics in the database
EXEC sp_updatestats;Reading execution plans is the single most valuable skill for SQL Server performance tuning. Start by looking for scans, key lookups, and high-cost operators. Use STATISTICS IO to measure logical reads, and always compare estimated vs actual rows. With practice, you will be able to diagnose and fix slow queries in minutes.
Try this query in UnifySQL
Write, optimize, and collaborate on SQL Server queries with AI assistance.
Start Free