Danette Dineen Riviello Magellan Health March 17, 2015 1.

27
Become a SQL Server Performance Detective Danette Dineen Riviello Magellan Health March 17, 2015 1

Transcript of Danette Dineen Riviello Magellan Health March 17, 2015 1.

Page 1: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Become a SQL Server Performance Detective

Danette Dineen RivielloMagellan HealthMarch 17, 2015

1

Page 2: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Game Plan

What triggers an Investigation? Emergent Performance Issues Chronic Performance Problems Solving the Case

2

Page 3: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Open a case

Increase in User ComplaintsApplication TimeoutsLong-running queriesOpen TransactionsChain of blocking

3

Page 4: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Look for Clues

Look at all running processes sp_who2 active

Look for one login or one database:

4

SELECT spid, [status],loginame [Login],hostname, blocked BlkBy,Db_name(dbid) DBName, cmd Command,cpu CPUTime,physical_io DiskIO,last_batch LastBatch,[program_name] ProgramName FROM master.dbo.sysprocesses where [status] not in ('sleeping')and loginame like '%login%'And Db_name(dbid) = 'DBName'ORDER BY dbname

Page 5: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Apprehend the Culprit

Look for the lead of a blocking chainSELECT spid,sp.STATUS ,loginame = SUBSTRING(loginame, 1, 12) ,hostname = SUBSTRING(hostname, 1, 12) ,blk = CONVERT(CHAR(3), blocked) ,open_tran ,dbname = SUBSTRING(DB_NAME(sp.dbid),1,10) ,cmd,waittype,program_name ,waittime ,last_batch ,SQLStatement = SUBSTRING ( qt.text, er.statement_start_offset/2, (CASE WHEN er.statement_end_offset = -1 THEN LEN(CONVERT(nvarchar(MAX), qt.text)) * 2 ELSE er.statement_end_offset END - er.statement_start_offset)/2 )FROM master.dbo.sysprocesses spLEFT JOIN sys.dm_exec_requests er ON er.session_id = sp.spidOUTER APPLY sys.dm_exec_sql_text(er.sql_handle) AS qtWHERE spid IN (SELECT blocked FROM master.dbo.sysprocesses)AND blocked = 0

5

Page 6: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Gather Evidence

Look at object locks

6

SELECT resource_type, object_name(resource_associated_entity_id), request_status, request_mode,request_session_id, resource_description FROM sys.dm_tran_locksWHERE resource_type = 'OBJECT'

Page 7: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Collect further clues

Look for open transactions

7

SELECT spid, [status],loginame [Login],hostname, blocked BlkBy,Db_name(dbid) DBName, cmd Command,cpu CPUTime,physical_io DiskIO,last_batch LastBatch,[program_name] ProgramName FROM master.dbo.sysprocesses WHERE open_tran>0ORDER BY spid

Page 8: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Search for the “Smoking Gun”

Find the line of code that is running:    SELECT [Spid] = session_Id      , ecid      , [Database] = DB_NAME(sp.dbid)      , [User] = nt_username      , [Status] = er.status      , [Wait] = wait_type      , [Individual Query] = SUBSTRING (qt.text,             er.statement_start_offset/2,      (CASE WHEN er.statement_end_offset = -1             THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2            ELSE er.statement_end_offset END -                                er.statement_start_offset)/2)      ,[Parent Query] = qt.text      , Program = program_name      , Hostname      , nt_domain      , start_time    FROM sys.dm_exec_requests er    INNER JOIN sys.sysprocesses sp ON er.session_id = sp.spid    CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) as qt    WHERE session_Id = @SPID          -- where @SPID is the one in Question    ORDER BY 1, 2

8

Page 9: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Investigate the environment What has changed? Look at default system trace:

9

Page 10: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Inspect System Trace Data

Look for recent changes

Look at the Log directory for prior files

10

Page 11: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Identify Chronic Offenders

To find most expensive stored procedures:

SELECT TOP 100 d.object_id, d.database_id, OBJECT_NAME(object_id, database_id) 'proc name', d.cached_time, d.last_execution_time, d.total_elapsed_time, d.total_elapsed_time/d.execution_count AS [avg_elapsed_time], d.last_elapsed_time, d.execution_countFROM sys.dm_exec_procedure_stats AS dORDER BY [total_worker_time] DESC;

11

Page 12: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Prioritize Worst Offenders Most expensive Stored procedure

runs

12

Page 13: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Set up a Profiler trace Job - Why

Less impact than an interactive trace Can load trace data on an alternate

server Can load trace data at a different

time of day Capture specific parameters passed Compare same time of day on

different days

13

Page 14: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Set up a Profiler trace Job - How

14

Page 15: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Set up a Profiler trace Job - How

15

Page 16: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Inspect the Profiler Trace File

Load the trace file to another serverselect * into dbo.tmp_loadtraceFile_ServerA_20150201_8FROM ::fn_trace_gettable('d:\trace_20150201_8.trc', 1)

Query trace file to find commands that are calling the suspected stored procedure select top 25 textdata, loginname, spid, duration, starttime, endtime, reads, cpuFrom dbo.tmp_loadtraceFile_ServerA_20150201_8Where textdata like '%offendingproc%'Order by duration desc

16

Page 17: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Inspect Profiler Trace Data

17

Page 18: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Retrieve the query plan

Use “Display Estimated Execution Plan”

Use “Include Actual Execution plan” Query to get query plans from DMV:

18

select top 25 st.text, qp.query_plan, qs.plan_handle from sys.dm_exec_query_stats qscross apply sys.dm_exec_sql_text(qs.sql_handle) stcross apply sys.dm_exec_query_plan(qs.plan_handle) qp

Page 19: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Examine long running procedures

Look at the query plan Missing index or wrong index

chosen? Look at the parameters sent in Check for other runs that perform

better Could it be a parameter sniffing

issue?

19

Page 20: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Parameter Sniffing - Defined Query plan developed based on the first

values passed to the procedure Pros:

Saves time: only one compile needed Cons:

Wrong query plan chosen

20

Page 21: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Parameter Sniffing - Detection

Look at Query plans If one procedure performs well in one

case and not others Do the index choices make sense?

21

Page 22: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Parameter Sniffing - Example

22

Page 23: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Parameter Sniffing – Solutions

Do Nothing Force Recompile each run

(expensive!) Query Hints (OPTIMIZE FOR) Break down stored procedures to

handle specific cases Education users on best parameter

choices

23

Page 24: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Rule out other culprits

Check for table scans caused by: Missing index Broad “where” clause

Check for improper join (many-to-many)

Check for too many tables in one join Use of a function in a large query

result set

24

Page 25: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Search for missing IndexesSELECT migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure, 'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle) + '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']' + ' ON ' + mid.statement + ' (' + ISNULL (mid.equality_columns,'') + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END + ISNULL (mid.inequality_columns, '') + ')' + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement, migs.*, mid.database_id, mid.[object_id]FROM sys.dm_db_missing_index_groups migINNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handleINNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handleWHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC

25

Page 26: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Solve the Case!

Solution may change over time Tables grow Statistics out of date Parameter Sniffing

Some problems result from multiple issues

Do least disruptive changes first: Add an index Close open connections

26

Page 27: Danette Dineen Riviello Magellan Health March 17, 2015 1.

Questions?

Thank you for attending!

Further questions: [email protected]

27