4. On The Inside
Relational Engine
Optimizer
Command
Parser
Query
Executor
SNI
User
Storage Engine
Buffer
Manager
Access
Methods
Transaction
Manager
SQL OS
Buffer Pool
Borrowed from Bradley Ball’s “SQL Internals, Recovery Models, & Backups” presentation
Plan Cache
Data
Cache
Data
5. Query Parsing
Relation Engine
1. Is the query syntactically correct?
SELECT [Nmae], [Number] FROM [Production].[Product]
Msg 207, Level 16, State 1, Line 3
Invalid column name 'Nmae'.
SELCT [Name], [Number] FROM [Production].[Product]
Msg 156, Level 15, State 1, Line 3
Incorrect syntax near the keyword 'FROM'.
2. No Errors Output as Parse Tree to Algebrizer
6. Query Parsing
SELECT [Nmae], [Number] FROM [Production].[Product]
Msg 207, Level 16, State 1, Line 3
Invalid column name 'Nmae'.
8. Algebrizer
1. Resolve the Names of the objects (tables, columns, etc.)
2. Resolve the data types for the objects being accessed.
3. Finds aggregate operations (min, max, group by) and performs an operation
called aggregate binding.
If the names of the objects, columns aren’t found an error is output and the process
halts.
If it is successful the algebrizer outputs the query processor tree to the query
optimizer. The query hash is generated and passed with the query processor tree.
9. Query Optimizer
1. The query optimizer checks the hash against the plan cache. If it exists use it and
the optimization step is skipped and plan is passed to query execution.
2. The query optimizer uses the query processor tree and the statistics to determine
an estimated execution plan.
3. The optimizer goes through a process of using different types of joins and indexes
and assigns a cost to each step by CPU and I/O and determines a cost for each
possible estimated plan it generates.
4. Once an acceptable estimated plan is found it is stored in the plan cache then sent
to the query execution.
10. Query Execution
Storage Engine
1. The storage engine determines if a recompile was triggered causing a change in
the estimated execution plan.
2. SQL Server determines based upon cost whether it exceeds the threshold for
parallelism changing the estimated plan for parallelism.
3. Statistics that have changed causing a change in the estimated plan.
SQL Server returns the results.
11. Cardinality Estimation
The optimization process depends on a cost estimation of each physical operator and the
estimated number of records (cardinality estimation) to be processed.
DBCC SHOW_STATISTICS ("[Sales].[SalesOrderDetailEnlarged]", [_WA_Sys_00000003_3D7E1B63]);
The accuracy of the cardinality estimation depends upon the distribution of values in one or
more columns of a table (statistics).
Name Updated Rows Rows Sampled Steps Average key length String Index Filter Expression Unfiltered Rows
_WA_Sys_00000003_3D7E1B63 Nov 26 2014 11:26AM 1000 1000 196 24 YES NULL 1000
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
002EE045-E30 0 1 0 1
0169388E-8EC 6 1 6 1
031622B3-B68 3 1 3 1
0424F840-4C2 3 1 3 1
04C4FEAC-7C1 3 1 3 1
13. Cardinality Estimation
There are multiple factors that can negatively impact the cardinality estimation process:
1. Out of date Statistics
SELECT object_name(object_id) as TableName, name AS stats_name,
STATS_DATE(object_id, stats_id) AS statistics_update_date
FROM sys.stats
WHERE object_id = OBJECT_ID('[Sales].[SalesOrderDetailEnlarged]');
2. Cardinality Estimation Errors
https://www.sqlskills.com/blogs/joe/cardinality-estimation-model-version/
16. Required Permissions
Server or database roles with permissions:
sysadmin, dbcreator or db_owner or showplan
To give showplan rights to the database:
GRANT SHOWPLAN TO [username];
21. Nested LoopNon-blocking
Description
For each row in the top (outer) input, scan the
bottom (inner) input, and output matching rows.
Where does it happen: Joins with
indexes on join columns.
22. Nested Loop
SELECT [sod].[CarrierTrackingNumber], [sod].[OrderQty], [soh].[RevisionNumber], [soh].[Ord
FROM [Sales].[SalesOrderHeader] soh
JOIN [Sales].[SalesOrderDetail] sod
ON sod.[SalesOrderID] = soh.[SalesOrderID]
WHERE soh.[OrderDate] = '2013-08-30 00:00:00.000'
Non-blocking
Outer
Inner
24. Description
Match rows from two suitably sorted input tables
exploiting their sort order.
Where does it happen: Joins with
indexes on join columns sorted in an
appropriate sort order.
MergeNon-blocking
27. Hash Match
Description
Use each row from the top input to build a hash
table, and each row from the bottom input to probe
into the hash table, outputting all matching rows.
Where does it happen: Missing Index,
Missing Where Clause, Where Clause
that is non-sargable.
28. Hash MatchBlocking
SELECT [sod1].[ProductID], [sod1].[CarrierTrackingNumber], [sod1].[UnitPrice], [sod1].[OrderQty]
FROM [Sales].[SalesOrderDetail] sod1
JOIN [Sales].[SalesOrderDetail] sod2
ON [sod1].[ProductID] = [sod2].[ProductID]
AND [sod1].[CarrierTrackingNumber] = [sod2].[CarrierTrackingNumber]
AND [sod1].[OrderQty] > 5
32. Parallelism
SELECT [sod1].[ProductID], [sod1].[CarrierTrackingNumber], [sod1].[UnitPrice], [sod1].[OrderQty]
FROM [Sales].[SalesOrderDetail] sod1
JOIN [Sales].[SalesOrderDetail] sod2
ON [sod1].[ProductID] = [sod2].[ProductID]
AND [sod1].[CarrierTrackingNumber] = [sod2].[CarrierTrackingNumber]
33. Parallelism
SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT [sod1].[ProductID], [sod1].[CarrierTrackingNumber], [sod1].[UnitPrice], [sod1].[OrderQty]
FROM [Sales].[SalesOrderDetail] sod1
JOIN [Sales].[SalesOrderDetail] sod2
ON [sod1].[ProductID] = [sod2].[ProductID]
AND [sod1].[CarrierTrackingNumber] = [sod2].[CarrierTrackingNumber]
SELECT [sod1].[ProductID], [sod1].[CarrierTrackingNumber], [sod1].[UnitPrice], [sod1].[OrderQty]
FROM [Sales].[SalesOrderDetail] sod1
JOIN [Sales].[SalesOrderDetail] sod2
ON [sod1].[ProductID] = [sod2].[ProductID]
AND [sod1].[CarrierTrackingNumber] = [sod2].[CarrierTrackingNumber]
OPTION(MAXDOP 1)
36. Hash Aggregate
SELECT [sod1].[CarrierTrackingNumber], sum([sod1].[UnitPrice]) UnitPriceTotal,
sum([sod1].[OrderQty]) as OrderQtyTotal
FROM [Sales].[SalesOrderDetail] sod1
JOIN [Sales].[SalesOrderDetail] sod2
ON [sod1].[ProductID] = [sod2].[ProductID]
AND [sod1].[CarrierTrackingNumber] = [sod2].[CarrierTrackingNumber]
AND [sod1].[OrderQty] > 5
GROUP BY [sod1].[CarrierTrackingNumber]
37. Stream Aggregate
SELECT [sod1].[CarrierTrackingNumber], sum([sod1].[UnitPrice]) UnitPriceTotal,
sum([sod1].[OrderQty]) as OrderQtyTotal
FROM [Sales].[SalesOrderDetail] sod1
JOIN [Sales].[SalesOrderDetail] sod2
ON [sod1].[ProductID] = [sod2].[ProductID]
AND [sod1].[CarrierTrackingNumber] = [sod2].[CarrierTrackingNumber]
AND [sod1].[OrderQty] > 5
GROUP BY [sod1].[CarrierTrackingNumber]
38. Sort (spill)
Operator used tempdb to spill data during execution with spill level 1
SELECT [sod].[CarrierTrackingNumber], [sod].[OrderQty], [soh].[RevisionNumber], [soh].[OrderDate]
FROM [Sales].[SalesOrderHeader] soh
JOIN [Sales].[SalesOrderDetailEnlarged] sod
ON sod.[SalesOrderID] = soh.[SalesOrderID]
WHERE [sod].[CarrierTrackingNumber] > '41D0-42A8-A5'
ORDER BY [soh].[RevisionNumber], [soh].[OrderDate]
39. Sort Spill
SELECT TOP 1 [sod].[CarrierTrackingNumber], [sod].[OrderQty], [soh].[RevisionNumber], [soh].[OrderDate]
FROM [Sales].[SalesOrderHeader] soh
JOIN [Sales].[SalesOrderDetailEnlarged] sod
ON sod.[SalesOrderID] = soh.[SalesOrderID]
WHERE [sod].[CarrierTrackingNumber] > '41D0-42A8-A5'
ORDER BY [soh].[RevisionNumber], [soh].[OrderDate]
40. Implicit Conversion
SELECT [sod].[ProductID], [sod].[CarrierTrackingNumber], [sod].[UnitPrice], [sod].[OrderQty], [rowguid]
FROM [Sales].[SalesOrderDetail] sod
WHERE LEFT([sod].[rowguid],4) = N'FE10'
44. Thank You!
Mike Lawell
Principal Consultant
Twitter: @SQLDiver
Blog: SQLServerAssociates.com
LinkedIn: LinkedIn.com/in/MikeLawell
Email: mike@sqlserverassociates.com
45. Who Am I?
Mike Lawell
Mike Lawell
Principal Consultant
Twitter: @SQLDiver
Blog: SQLServerAssociates.com
LinkedIn: LinkedIn.com/in/MikeLawell
Editor's Notes
Object Names, Data types, Aggregate Binding
Is it in plan cache?
Estimated plan(s)
Costs per plan?
Sent to Storage Engine for execution.
Is did recompile get triggered?
Over cost threshold for parallelism?
Cardinality Estimation Model Version 120 (new model) 70 old model.
Cardinality Estimation Model Version 120 (new model) 70 old model.
Physical order of process is SELECT pulls data from the next operator left to right top to bottom.
Easier to understand from right to left top to bottom.
Seeing a hash match is a good indication of an opportunity for tuning by adding an index, improving the join or where clause. If that isn’t possible, the hash match is the most efficient option you have.
Table results are inserted into a temporary table and columns hashed for each table then matched from the temporary table. It is a blocking process as it must populate the hash tables completely before it can match the hash values for output.