Reading Execution Plans: The Deep Dive€¦ · Grant Fritchey | Reading Execution Plans: The Deep...
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: [email protected]
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: [email protected]
Grant Fritchey | www.ScaryDBA.com
Questions?
36