{"id":408,"date":"2008-07-24T00:00:00","date_gmt":"2008-07-24T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/investigating-sql-server-2008-wait-events-with-xevents\/"},"modified":"2021-06-03T16:44:21","modified_gmt":"2021-06-03T16:44:21","slug":"investigating-sql-server-2008-wait-events-with-xevents","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/performance-sql-server\/investigating-sql-server-2008-wait-events-with-xevents\/","title":{"rendered":"Investigating SQL Server 2008 Wait Events with XEVENTS"},"content":{"rendered":"<div id=\"pretty\">\n<h1>Investigating perfomance bottlenecks in &#160;SQL Server 2008 by&#160;looking at wait events using the XE trace system<\/h1>\n<h3>Introduction.<\/h3>\n<p>In my previous articles&#160; <a href=\"http:\/\/www.simple-talk.com\/sql\/performance\/sql-server-wait-events-taking-the-guesswork-out-of-performance-profiling\/\">SQL Server Wait Events: Taking the Guesswork out of Performance Profiling<\/a>,&#160; and <a href=\"http:\/\/www.simple-talk.com\/sql\/performance\/taking-the-guesswork-out-of-sql-server-performance-profiling-part-2\/\">Taking the Guesswork out of SQL Server Performance Profiling Part 2,<\/a> I introduced the concepts of performance analysis based on wait events.<\/p>\n<p>In short, the idea behind this concept is to take the response time of a SQL statement (or a batch or a user session) and split it up into CPU time and Wait time..<\/p>\n<p>Earlier versions of SQL Server only maintain wait time (aggregated) on the server level, or you can see the wait times and the wait reasons, and when they actually occur in views like <b><i>sysprocesses<\/i><\/b> or <b><i>sys.dm_os_waiting_tasks<\/i><\/b>. Starting with SQL Server 2005, the wait events are finally documented in the SQL Server BOL, and more and more background is provided in blogs, KB Articles, forums etc.<\/p>\n<p>A wait event &#8216;happens&#8217; when the SQL Server scheduler (implemented in the SQLOS) decides to suspend a running task.<\/p>\n<p>This can be because a &#8216;long&#8217; operation starts, such as disk, &#160;network I\/O, or &#160;lock. It can also happen when the allotted time quantum that a task can be active on the CPU ends. At this moment this seems to be a hard-coded 4 ms. This is the means by which that the SQL Server scheduler makes sure that every task in SQL Server gets its turn running on the CPU. By carefully looking at the way the response time is build up, one can make intelligent decisions on where to look for possible optimizations, or capacity planning: For instance, if on your SQL Server box 90% of the total used (response) time consists of I\/O waits and only 10% of the time is spend on the CPU, then adding CPU capacity or upgrading to faster CPUs is unlikely to have a very large impact on response times. The same is true for individual queries. If one query spends 90% of its time waiting for I\/O, then speeding up the CPU will only impact the other 10% of the response time picture.<\/p>\n<p>SQL Server 2008 introduces Extended Events (XE) a new event handling system. XE is a flexible and lightweight event trace system.<\/p>\n<p>The SQL Server engine is instrumented with tracing code in many locations. It is possible to trace &#8216;traditional&#8217; events as existed in older SQL Trace versions, events like &#8216;<b>RPC:Completed&#8217;<\/b>. &#8216;<b>sp_completed&#8217;<\/b>, &#8216;<b>lock timeout&#8217;<\/b> etc.<\/p>\n<p>An exciting new tracing feature, is the means by which one can trace information about SQL Server OS (SQLOS) wait events<\/p>\n<p>Each event contains a set of interesting columns that will be logged to a &#8216;target&#8217;. In this example, we have chosen a file. Next to the &#8216;default&#8217; set of columns for an event, extra information can be logged as well. This is done by defining &#8216;actions&#8217; on a traced event. Below is an example of standard columns that are logged for the event <b>&#8216;wait_info&#8217;<\/b> in the package &#8216;<b>sqlos<\/b>&#8216;, and for the event, &#8216;<b>sql_statement_completed&#8217;<\/b> in the <b>sqlserver<\/b> package, which will also be used in the example:<\/p>\n<pre>name&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; column_id&#160;&#160;&#160;&#160;&#160;&#160; object_name&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n--------------------&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;-----------&#160;&#160;&#160;&#160; -----------------------&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \nwait_type&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;0&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; wait_info&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \nopcode&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; wait_info&#160; \nduration&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;2&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; wait_info&#160; \nmax_duration&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;3&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; wait_info&#160; \ntotal_duration&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; wait_info&#160; \nsignal_duration&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;5&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; wait_info&#160; \ncompleted_count&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;6&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; wait_info\n...\nsource_database_id&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 0&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sql_statement_completed\nobject_id&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sql_statement_completed\nobject_type&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 2&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sql_statement_completed\ncpu&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;3&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sql_statement_completed\nduration&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160; &#160;&#160;4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sql_statement_completed\nreads&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160; &#160;5&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sql_statement_completed\nwrites&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160; &#160;6&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sql_statement_completed\n<\/pre>\n<p>Next is an example on how to setup wait event tracing and collecting information from an &#8216;asynchronous file target&#8217;.&#160; Only specific events are collected for session_id=53.<\/p>\n<p>First we create the &#8216;event session&#8217;, and start it.<\/p>\n<p>After this, we can run an example query from a session with session_id=53, a count(*) query was run on a 1 million row (unindexed) table.<\/p>\n<h3>Example 1:<\/h3>\n<pre class=\"theme:ssms2012 lang:tsql\">\ncreate event session test1\non server\nadd event sqlserver.sql_statement_starting\n(action \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160; (sqlserver.session_id, package0.collect_system_time,\npackage0.collect_cpu_cycle_time,sqlserver.sql_text,\nsqlserver.plan_handle, sqlos.task_address, sqlos.worker_address)\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; where sqlserver.session_id = 53),\nadd event sqlserver.sql_statement_completed\n(action \n(sqlserver.session_id, package0.collect_system_time, package0.collect_cpu_cycle_time, sqlserver.sql_text,\nsqlserver.plan_handle, sqlos.task_address, sqlos.worker_address)\n&#160;&#160;&#160;&#160;&#160; where sqlserver.session_id = 53),\nadd event sqlos.wait_info\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; (action \n(sqlserver.session_id,&#160; package0.collect_system_time, package0.collect_cpu_cycle_time, sqlos.task_address, sqlos.worker_address)\n&#160;&#160;&#160;&#160;&#160;&#160; where sqlserver.session_id = 53)\n--\n--&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160; async file, read with: sys.fn_xe_file_target_read_file\n--\n&#160;ADD TARGET package0.asynchronous_file_target\n(SET filename = N'C:\\temp\\wait.etx', metadatafile = N'C:\\temp\\wait.mta',\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; max_file_size = 50, max_rollover_files = 10) \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WITH (max_dispatch_latency = 2 seconds)\ngo\nalter event session test1 on server state = start\ngo\n<\/pre>\n<h3>Example 2:<\/h3>\n<p>The next example shows how to collect the trace information from the trace files for further processing. As you can see from the example, the files is read &#8216;through&#8217; a virtual function, &#8216;sys.fn_xe_file_target_read_file&#8217;, and the rows are returned in XML form.<\/p>\n<p>The insert into the xTable counted 4938 rows. For the next summary I only collected the &#8216;wait_info&#8217; &#8216;end&#8217; events (1560 rows) and the &#8216;sql_statement_completed&#8217; event (1 row):<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">drop table xTable\nCREATE TABLE xTable \n&#160;&#160;&#160; ( \n&#160;&#160;&#160;&#160;&#160; xTable_ID INT IDENTITY \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; PRIMARY KEY, \n&#160;&#160;&#160;&#160;&#160; xCol XML \n&#160;&#160;&#160; ) ; \n&#160;\nINSERT&#160; INTO xTable ( xCol ) \nselect cast(event_data as xml) waitinfo from sys.fn_xe_file_target_read_file\n('c:\\temp\\wait_*.etx',\n'c:\\temp\\wait_*.mta',\nnull,null)\n<\/pre>\n<p>Now in order to extract the CPU and Wait information and match it with the total response time, we run the following queries:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">SELECT&#160; \n-- for some reason wait type name is not logged with synch target. bug?\n(select map_value from sys.dm_xe_map_values \n&#160;&#160;&#160; where name = 'wait_types' \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; and map_key = xCol.value('(event\/data\/value)[1]', 'int') \n)AS wtype,\n&#160;&#160;&#160;&#160; xCol.value('(event\/data\/value)[3]', 'int')&#160; --wait time\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS tottime,\n&#160;&#160;&#160;&#160; xCol.value('(event\/data\/value)[6]', 'int') --sig wait time\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS sigtime\n&#160;&#160;&#160;&#160; into #mywaits&#160;&#160;&#160; \nFROM&#160;&#160;&#160; xTable \nwhere xCol.value('(\/event\/@name)[1]', 'varchar(30)') = 'wait_info'&#160;&#160;&#160;&#160;&#160; \n&#160;and xCol.value('(event\/data\/value)[2]', 'int') = 1 --opcode end&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n&#160;\nselect&#160; wtype, \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; count(*) as wcount, \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; sum(tottime) as total_time, \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; sum(sigtime) as signal_time \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; from #mywaits group by wtype\ngo\n-- stmt completed:\n&#160;\nSELECT&#160; \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/data\/value)[4]', 'int')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS cputime,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/data\/value)[5]', 'int')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS duration,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[4]', 'varchar(MAX)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS sql_text\ninto #mysql\nFROM&#160;&#160;&#160; [xTable] \nwhere xCol.value('(\/event\/@name)[1]', 'varchar(30)') = 'sql_statement_completed'&#160;&#160;&#160;&#160; \nselect&#160; sql_text, \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; count(*) as count, \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; SUM(cputime) as cputime, \n&#160;&#160;&#160;&#160;&#160;&#160;&#160; SUM(duration) as duration from #mysql group by sql_text\ngo\ndrop table #mywaits\ndrop table #mysql\n<\/pre>\n<p>This is the result of the above queries:<\/p>\n<pre>&#160;&#160; wtype&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; wcount&#160;&#160;&#160; &#160;&#160;&#160;&#160; total_time&#160;&#160;&#160; signal_time&#160;&#160;&#160; --------------------------&#160; ----------- &#160;&#160; ----------- &#160; -----------&#160;&#160;&#160; \nPWAIT_SOS_SCHEDULER_YIELD&#160;&#160;&#160;20&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 45&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160; 0&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \nPWAIT_SLEEP_TASK&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160; 10&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160; 0&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \nPWAIT_PAGEIOLATCH_SH&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1539&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 59163&#160;&#160; &#160;&#160;&#160;&#160;&#160; 674&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n&#160;(1 row(s) affected)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\nsql_text&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; count&#160;&#160;&#160;&#160;&#160; cputime&#160;&#160; duration&#160;&#160;&#160;&#160;&#160;&#160; \n------------------------- &#160;&#160;--------&#160;&#160; -------- &#160;-----------&#160;&#160;&#160; \nselect COUNT(*) from t1m&#160;&#160;&#160;&#160;1&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1892&#160;&#160;&#160;&#160;&#160;&#160;61560364&#160;&#160;&#160;&#160;&#160;&#160; \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n<\/pre>\n<p>So what we can see here is that the statement response time (duration) was 6156 ms (apparently, the&#160; <b>sqlserver.sql_statement_completed.duration<\/b> is measured in microseconds)<\/p>\n<p>The CPU time used was 1892 ms and the wait time for the three different wait events was 45+10+59163 ms = 59218 ms. Including the measured signal_time (the time between the end of the actual wait and the resumption of work) this nicely adds up to the total duration of the query.<\/p>\n<p>For more information on the specific wait events, search the SQL Server BOL for the <b>sys.dm_os_wait_stats<\/b> view. All wait events are documented here.<\/p>\n<p>It is also possible to look at each individual wait event. This can be useful to detect skew in wait durations for example. If you detect that certain I\/O operations take longer than others, it might be interesting to add other XEvents to trace. Events like &#8216;<b>file_read_completed&#8217;<\/b> will show which file was read and which offset within the file. The event &#8216;<b>physical_page_read&#8217;<\/b>, can tell which page for which file. These events can help detecting if you might be reading from slow disks or doing random I\/O while you were expecting to do sequential I\/Os.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">-- first: sql_statement_starting\nSELECT&#160; xTable_ID,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[1]', 'int')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS session_id,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(\/event\/@timestamp)[1]', 'varchar(24)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS EventTime,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(\/event\/@name)[1]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS EventType,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[2]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS system_time,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[3]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS cpu_cycle_time,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/data\/value)[5]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS data1,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/data\/value)[6]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS data2,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[4]', 'varchar(MAX)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS sql_text\nFROM&#160;&#160;&#160; [xTable] \nwhere xCol.value('(\/event\/@name)[1]', 'varchar(30)') = 'sql_statement_starting'\nunion&#160;&#160;&#160; --now collect: statement_completed&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \nSELECT&#160; xTable_ID,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[1]', 'int')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS session_id,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(\/event\/@timestamp)[1]', 'varchar(24)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS EventTime,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(\/event\/@name)[1]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS EventType,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[2]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS system_time,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[3]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS cpu_cycle_time,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/data\/value)[4]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS data1,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/data\/value)[5]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS data2,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[4]', 'varchar(MAX)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS sql_text\nFROM&#160;&#160;&#160; [xTable] \nwhere xCol.value('(\/event\/@name)[1]', 'varchar(30)') = 'sql_statement_completed'\nunion\nSELECT&#160; xTable_ID,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[1]', 'int')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS session_id,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(\/event\/@timestamp)[1]', 'varchar(24)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS EventTime,\n-- for some reason wait type name is not logged with synch target. bug?\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;(select map_value from sys.dm_xe_map_values \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; where name = 'wait_types' \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; and map_key =&#160; xCol.value('(event\/data\/value)[1]', 'int') \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) as Event_name,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[2]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS system_time,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; xCol.value('(event\/action\/value)[3]', 'varchar(30)')\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS cpu_cycle_time,\nxCol.value('(event\/data\/value)[3]', 'varchar(30)')&#160; --wait&#160;time\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS data1,\nxCol.value('(event\/data\/value)[6]', 'varchar(30)') --sig wait time\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS data2,\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ''\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AS sql_text\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \nFROM&#160;&#160;&#160; [xTable] \nwhere xCol.value('(\/event\/@name)[1]', 'varchar(30)') = 'wait_info'&#160;&#160;&#160;&#160;&#160; \n&#160;and xCol.value('(event\/data\/value)[2]', 'int') = 1 -- opcode end&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \n&#160;\n\n<\/pre>\n<p class=\"note\">This article, submitted in May, was originally scheduled for publication as part of Simple-Talk&#8217;s celebration of the launch of SQL Server 2008 next month, but has been brought forward in view of the current interest in the subject <\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Some reasons for the slow-running of database applications aren&#8217;t obvious. Occasionally, even the profiler won&#8217;t tell you enough to remedy a problem, especially when a SQL Statement is being forced to wait.<br \/>\nNow, in SQL Server 2008, come XEvents, which allow you to look at those wait events that are slowing your SQL Statements.<br \/>\nMario Broodbakker continues his series about SQL Server Wait Events<br \/>\nSQL Server 2008 wait event based performance analysis using XEvents&hellip;<\/p>\n","protected":false},"author":129582,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143529],"tags":[4168,4206,4150,4151],"coauthors":[],"class_list":["post-408","post","type-post","status-publish","format-standard","hentry","category-performance-sql-server","tag-database","tag-performance","tag-sql","tag-sql-server"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/408","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/129582"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=408"}],"version-history":[{"count":6,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/408\/revisions"}],"predecessor-version":[{"id":91218,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/408\/revisions\/91218"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=408"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=408"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=408"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=408"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}