Execution Plans for Mere Mortals A beginners look at execution plans. Mike Lawell, Teammate, Linchpin People
2 Please silence cell phones 2
3 Explore Everything PASS Has to Offer FREE SQL SERVER AND BI WEB EVENTS FREE 1-DAY TRAINING EVENTS REGIONAL EVENT LOCAL USER GROUPS AROUND THE WORLD FREE ONLINE TECHNICAL TRAINING THIS IS COMMUNITYBUSINESS ANALYTICS TRAINING SESSION RECORDINGSPASS NEWSLETTER 3
Agenda We will be taking a look at Graphical Execution Plans from a beginners perspective. The ride will include the following: Execution Steps Execution Plan Basics Basic Operators Join Operators Other Operators 4
Execution Step by Step
6 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 *SQL Server Network Interface (SNI)
Relation Engine 1.Is the query syntactically correct? SELECT [Name], [Number] FORM [Production].[Product] Incorrect syntax near 'Production'. 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 Query Parsing 7
8 SELECT [Name], [Number] FORM [Production].[Product] Incorrect syntax near 'Production'.
9 Query Parsing SELECT [Name], [Number] FROM [Production].[Product]
10 Execute Parallel/ Not Parallel Store in Plan Cache (*) Find Plan Hash Checked in Plan Cache Aggregate Binding Resolve Data Types Name Resolution Plan Creation Algebrizer Query Optimizer Recompile? Storage Engine No Results Returned 7 Cost > Cost for Parallelism 8 YES Does Plan Exist? Create Plan NO Yes
11 Execute Parallel/ Not Parallel Store in Plan Cache (*) Find/Create Plan Hash Checked in Plan Cache Aggregate Binding Resolve Data Types Name Resolution Plan Creation Does Plan Exist? Algebrizer Query Optimizer Yes Recompile? No Storage Engine No Results Returned 7 Cost > Cost for Parallelism 8 When a plan is found, good enough or optimal, then it is stored in cache (*). *If optimize for adhoc workloads is enabled, a stub is saved the first execution. If a recompile has been triggered, the process starts over. Is cost > cost for threshold? If it is, parallelize query. The algebrizer finds aggregate operations and performs aggregate binding. The algebrizer resolves the data types for the objects being accessed. The algebrizer resolves the names for objects (tables, columns, etc). Check the query hash against the plan cache to see if it exists If it doesn’t exist, use the query processor tree and statistics to determine execution plan generating multiple plans assigning cost (CPU, I/O) to each step and picks the best one.
12 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_ _3D7E1B63]); The accuracy of the cardinality estimation depends upon the distribution of values in one or more columns of a table (statistics). NameUpdatedRowsRows SampledStepsAverage key lengthString IndexFilter ExpressionUnfiltered Rows _WA_Sys_ _3D7E1B63Nov :26AM YESNULL1000 RANGE_HI_KEYRANGE_ROWSEQ_ROWSDISTINCT_RANGE_ROWSAVG_RANGE_ROWS 002EE045-E E-8EC B3-B F840-4C C4FEAC-7C13131 Create Plan 5
13 Cardinality Estimation There are multiple factors that can negatively impact the cardinality estimation process: 1. 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. 2.Cardinality Estimation Errors
14 Which cardinality version am I using?
Execution Plan Basics Getting Started
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];
How to Read
Basic Operators Start Here
Basic Operators DML StatementsAccess Methods 19 Other Operators
Join Operators Making it Happen
21 Nested Loop Non-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.
Nested Loop SELECT [sod].[CarrierTrackingNumber], [sod].[OrderQty], [soh].[RevisionNumber], [soh].[OrderDate] FROM [Sales].[SalesOrderHeader] soh JOIN [Sales].[SalesOrderDetail] sod ON sod.[SalesOrderID] = soh.[SalesOrderID] WHERE soh.[OrderDate] = ' :00:00.000' Outer Loop Inner Loop Non-blocking 22
23 Nested Loop
24 Non-blocking Nested Loop SalesOrderIDRevisionNumberOrderDate :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: SalesOrderIDProductIDCarrierTrackingNumberOrderQty E E E E E E E E E E E E E E E E E E E E-951
25 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. Merge Non-blocking
Merge SELECT [sod].[CarrierTrackingNumber], [sod].[OrderQty], [soh].[RevisionNumber], [soh].[OrderDate] FROM [Sales].[SalesOrderHeader] soh JOIN [Sales].[SalesOrderDetail] sod ON sod.[SalesOrderID] = soh.[SalesOrderID] Non-blocking 26
27 Merge SalesOrderIDRevisionNumberOrderDate :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: :00: SalesOrderIDProductIDCarrierTrackingNumberOrderQty E E E E E E E E E E E E E E E E E E E E-951 Non-blocking
28 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.
Hash Match Blocking 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 29
Hash Match Hash Table Blocking 30 Column A Column B Hashed Value 8Ax94Dd343S 8Ax94Dd343S
Hash Match Hash Table 1 Blocking 31 8Ax94Dd343S 1) From the first input (table) the column data is hashed and put in buckets in a “hash” table (in tempdb). 2) Then it reads rows from input 2, hashes the join columns and compares the hash and values to output matches. 8Ax94Dd343S 8Bx40XdF43D 8CxXDVa91f If a Match… “Send” row data to next operator and go to the next row.
32 Fixed Hash Match
Other Operators Fun Stuff
34 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]
35 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 Parallelism
37 Parallelism
38 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]
39 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]
40 Sort Spill Operator used tempdb to spill data during execution with spill level 2 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]
41 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]
42 Implicit Conversion SELECT [sod].[CarrierTrackingNumber], [sod].[OrderQty], [soh].[RevisionNumber], [soh].[OrderDate] FROM [Sales].[SalesOrderHeaderEnlarged] soh JOIN [Sales].[SalesOrderDetailEnlarged] sod ON sod.[SalesOrderID] = soh.[SalesOrderID] WHERE CONVERT(varchar(10),[soh].[OrderDate],110) = ' '
43 Cool Tools/Products SQL Server Query Plan Analysis by Joe Sack
44 Resources
45 Session Evaluations ways to access Go to passsummit.com/evals Download the GuideBook App and search: PASS Summit 2015 Follow the QR code link displayed on session signage throughout the conference venue and in the program guide Submit by 5pm Friday November 6 th to WIN prizes Your feedback is important and valuable. 45
46 Mike Lawell Principal Consultant Blog:SQLServerAssociates.com LinkedIn:LinkedIn.com/in/MikeLawell
47 Properties
50 Palette PRIMARY PALETTESECONDARY PALETTE 50
Titles are set 36 Segoe UI, maximum 2 lines, ideally 1 line Heading One Style, 28pt Body content, 18pt Segoe UI (gray) Heading Two Style, 24pt Body content, 18pt Segoe UI (gray) HEADING THREE STYLE, 16pt, BOLD, ALL CAPS Body content, 18pt Segoe UI (gray) 51
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. Algebrizer
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. The query optimizer uses the query processor tree and the statistics to determine an estimated execution plan. 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. Once an acceptable estimated plan is found it is stored in the plan cache then sent to the query execution. Query Optimizer
Storage Engine The storage engine determines if a recompile was triggered causing a change in the estimated execution plan. SQL Server determines based upon cost whether it exceeds the threshold for parallelism changing the estimated plan for parallelism. Statistics that have changed causing a change in the estimated plan. SQL Server returns the results. Query Execution