Reading Execution Plans: The Deep Dive€¦ · Grant Fritchey | Reading Execution Plans: The Deep...

Post on 01-Aug-2020

3 views 1 download

Transcript of Reading Execution Plans: The Deep Dive€¦ · Grant Fritchey | Reading Execution Plans: The Deep...

Grant Fritchey | www.ScaryDBA.com

www.ScaryDBA.com

Reading Execution

Plans: The Deep Dive

for PASS Performance Virtual Chapter 4/26/12

Grant Fritchey

Grant Fritchey | www.ScaryDBA.com

Grant Fritchey

Product Evangelist for Red Gate Software

Twitter: @gfritchey

Blog: scarydba.com

Email: grant@scarydba.com

Grant Fritchey | www.ScaryDBA.com

A Query

SELECT soh.PurchaseOrderNumber, soh.AccountNumber, p.Name, sod.OrderQty, sod.LineTotal, cc.CardNumber FROM Sales.SalesOrderHeader AS soh JOIN Sales.SalesOrderDetail AS sod ON soh.SalesOrderID = sod.SalesOrderID JOIN Production.Product AS p ON sod.ProductID = p.ProductID JOIN Sales.CreditCard AS cc ON soh.CreditCardID = cc.CreditCardID

3

Grant Fritchey | www.ScaryDBA.com

A plan

4

Grant Fritchey | www.ScaryDBA.com

The Select Operator

5

Grant Fritchey | www.ScaryDBA.com

Clustered Index Scan

6

Grant Fritchey | www.ScaryDBA.com

Merge Join

7

Grant Fritchey | www.ScaryDBA.com

Hash Join

8

Grant Fritchey | www.ScaryDBA.com

The Pipe

9

Grant Fritchey | www.ScaryDBA.com

Compute Scalar

10

Grant Fritchey | www.ScaryDBA.com

An Entirely New Query

SELECT soh.PurchaseOrderNumber, soh.AccountNumber, p.Name, sod.OrderQty, sod.LineTotal, cc.CardNumber FROM Sales.SalesOrderHeader AS soh JOIN Sales.SalesOrderDetail AS sod ON soh.SalesOrderID = sod.SalesOrderID JOIN Production.Product AS p ON sod.ProductID = p.ProductID JOIN Sales.CreditCard AS cc ON soh.CreditCardID = cc.CreditCardID WHERE soh.CustomerID = 24624

11

Grant Fritchey | www.ScaryDBA.com

An Entirely New Query

SELECT soh.PurchaseOrderNumber, soh.AccountNumber, p.Name, sod.OrderQty, sod.LineTotal, cc.CardNumber FROM Sales.SalesOrderHeader AS soh JOIN Sales.SalesOrderDetail AS sod ON soh.SalesOrderID = sod.SalesOrderID JOIN Production.Product AS p ON sod.ProductID = p.ProductID JOIN Sales.CreditCard AS cc ON soh.CreditCardID = cc.CreditCardID WHERE soh.CustomerID = 24624

12

Grant Fritchey | www.ScaryDBA.com

A New Plan

13

Grant Fritchey | www.ScaryDBA.com

The Select Operator 2

14

Grant Fritchey | www.ScaryDBA.com

Index Seek

15

Grant Fritchey | www.ScaryDBA.com

Nested Loop Join

16

Grant Fritchey | www.ScaryDBA.com

Key Lookup

17

Grant Fritchey | www.ScaryDBA.com

Stored Procedure

IF (SELECT OBJECT_ID('spAddressByCity')

) IS NOT NULL

DROP PROCEDURE dbo.spAddressByCity ;

GO

CREATE PROC dbo.spAddressByCity @City NVARCHAR(30)

AS

SELECT a.AddressID,

a.AddressLine1,

a.AddressLine2,

a.City,

sp.[Name] AS StateProvinceName,

a.PostalCode

FROM Person.Address AS a

JOIN Person.StateProvince AS sp

ON a.StateProvinceID = sp.StateProvinceID

WHERE a.City = @City ;

18

Grant Fritchey | www.ScaryDBA.com

The Plan

19

Grant Fritchey | www.ScaryDBA.com

Sort

20

Grant Fritchey | www.ScaryDBA.com

The Select Operator 3

21

Grant Fritchey | www.ScaryDBA.com

The Plan?

22

Grant Fritchey | www.ScaryDBA.com

The Select Operator 4

23

Grant Fritchey | www.ScaryDBA.com

Delete Query

BEGIN TRAN

DELETE FROM Production.Product

WHERE ProductID = 3343

ROLLBACK TRAN

24

Grant Fritchey | www.ScaryDBA.com

The Plan

25

Grant Fritchey | www.ScaryDBA.com

Delete Operator

26

Grant Fritchey | www.ScaryDBA.com

Assert

27

Grant Fritchey | www.ScaryDBA.com

Table Spool

28

Grant Fritchey | www.ScaryDBA.com

A View

SELECT ve.FirstName,

ve.LastName,

ve.BusinessEntityID

FROM HumanResources.vEmployee AS ve

WHERE ve.BusinessEntityID = 221

29

Grant Fritchey | www.ScaryDBA.com

View Execution Plan

30

Grant Fritchey | www.ScaryDBA.com

The Real Plan

31

Grant Fritchey | www.ScaryDBA.com

A little XML

WITH XMLNAMESPACES(DEFAULT N'http://schemas.microsoft.com/sqlserver/2004/07/showplan'),

QueryPlans AS

(

SELECT RelOp.pln.value(N'@PhysicalOp', N'varchar(50)') AS OperatorName,

RelOp.pln.value(N'@NodeId',N'integer') AS NodeId,

RelOp.pln.value(N'@EstimateCPU', N'decimal(10,9)') AS CPUCost,

RelOp.pln.value(N'@EstimateIO', N'decimal(10,9)') AS IOCost,

dest.text

FROM sys.dm_exec_query_stats AS deqs

CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest

CROSS APPLY sys.dm_exec_query_plan(deqs.plan_handle) AS deqp

CROSS APPLY deqp.query_plan.nodes(N'//RelOp') RelOp (pln)

)

SELECT qp.OperatorName,

qp.NodeId,

qp.CPUCost,

qp.IOCost,

qp.CPUCost + qp.IOCost AS EstimatedCost

FROM QueryPlans AS qp

WHERE qp.text LIKE 'SELECT * FROM HumanResources.vEmployee AS ve'

ORDER BY EstimatedCost DESC

32

Grant Fritchey | www.ScaryDBA.com

What To Look For

First Operator

Warnings

Most Costly Operations

Fat Pipes

Extra Operations

Scans

Grant Fritchey | www.ScaryDBA.com

Resources

Scarydba.com/Resources

34

Grant Fritchey | www.ScaryDBA.com

Grant Fritchey

Product Evangelist for Red Gate Software

Twitter: @gfritchey

Blog: scarydba.com

Email: grant@scarydba.com

Grant Fritchey | www.ScaryDBA.com

Questions?

36