Introduction to SQL Server
Execution Plan
Agenda
Introductions
The Query Optimizer
Commonly used operators
Blocking and non-blocking operators
The Query Optimizer
Why do we need an optimizer?
T-SQL is a What not how language.
We write logical requests.
SQL Optimizer Engine converts
logical requests into physical
plans.
Query Optimization (in a bit more
detail)
Optimizer steps
Parse
Bind
Optimize
Execute
Commonly used operators
SELECT
UPDATE
INSERT
DELETE
Table scan
Clustered
Index Scan
NonClustered
Index Scan
Clustered
Index Seek
NonClustered
Index Seek
Key Lookup
Nested Loop
Join
Merge Join
Hash Join
Index Operations Table Scans
Table Scan Heap (no clustered index)
Generally not a best practice for data retrieval
When Table Scans Are Acceptable
Small tables
Table variables
CTE functionality
Heavily inserted tables, minimal selects/updates/deletes
Index Operations Index Scans
Clustered Index Scans
Same as a table scan but table is sorted on disk
Generally slightly better than heap operations for CPU usage
Query could most likely benefit from different index
Could also mean the large range of data is been selected
Index Operations Index Scans
Non-Clustered Index Scan
Less data scanned than a clustered index
Causes for non-clustered index scan
Not an optimal index for the query
Seek predicate is not SARGable
Dataset returned represents most of the table
Index Operations Index Seeks
Clustered Index Seek
Most preferred method for data retrieval
Downside, only one clustered index can exist on the table
Index Operations Index Seeks
Non-Clustered Index Seek
As good as clustered index seek
Upside, can have multiple non-clustered indexes
Downside, over indexing tables can cause slowdowns on writes
Index Operations - Lookups
Lookups What are they?
Only on non-clustered index operations
RID Lookup (Heap) - no clustered index present
Key Lookup (Clustered) - clustered key lookup
Eliminating lookups
RID Lookup
alter the existing non-clustered index by adding non-index column to it;
drop the non-index column from the query;
consider a different indexing strategy for this table altogether; or,
leave the lookup in place and hope it never becomes a performance sore
point
Key Lookup
Create a non-clustered index taking all the columns in select statement
Join Operations Hash Join
Hash joins - How it works
Two phases - build phase, probe phase
Build phase - Scans or computes build input and builds hash table
in memory (if possible)
Probe phase - For each row of probe input hash value is build or
computed than compared against hash bucket of the build input,
either producing matches or not
Requires at least one equality statement
Performed when at least one side of the join is not
properly indexed (index scan/table scan)
Most common join operation
Join Operation Nested Loop
Nested loop join How it works
Also called nested iteration, builds two inputs - inner and
outer input
Outer input (displayed on top in the execution plan)
Processes row by row against inner output
A smaller table in the join predicate
Inner input (on the bottom of the execution plan)
Scanned for every row of the outer input to produce matches
A larger table of the two participating in the join
Has to be properly indexed ( index seeks)
Usually used when one table in the join is relatively small and
the other is rather large, and at least one table (larger) is
properly indexed.
If those conditions are met generally outperforms hash join
operations
Join Operations - Merge
Merge join How it works
Both tables participated in the join must be sorted on the join
columns. If that condition is not met, merge join operation
would require an explicit sort which could be very costly.
Both inputs are scanned once at the same time, one row at a
time, and if the rows are not matched, the row is discarded.
Since both inputs are sorted, we can guarantee we will not
see another possible match.
Blocking and Non-blocking Operators
Operators / Iterators can be put in two categories:
1. Blocking 2. Non-blocking Having a blocking operator in your plan means
other operators further down the line are sitting
idle.
This will reduce the overall performance of your
query
Putting it all Together
Again Right-to-left approach
Index operation priorities Seek-> Scan-> Heap
Join operation priorities Merge->NL-> Hash
Advanced options
MAXDOP
INDEX HINTS
OPTIMIZE FOR
JOIN HINTS