© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2023
P. A. CarterPro SQL Server 2022 Administrationhttps://doi.org/10.1007/978-1-4842-8864-1_20

20. Extended Events

Peter A. Carter1  
(1)
SOUTHAMPTON, UK
 

Extended Events are a lightweight monitoring system offered by SQL Server. Because the architecture uses so few system resources, they scale very well and allow you to monitor their instances, with minimal impact on user activity. They are also highly configurable, which gives you in your role as a DBA a wide range of options for capturing details from a very fine grain, such as page splits, to higher-level detail, such as CPU utilization. You can also correlate Extended Events with operating system data to provide a holistic picture when troubleshooting issues. The predecessor to Extended Events was SQL Trace, and its GUI, called Profiler. This is now deprecated for use with the Database Engine, and it is recommended that you only use it for tracing Analysis Service activity.

In this chapter, we will discuss the concepts associated with Extended Events, before discussing how to implement the technology. Finally, we will discuss how to integrate them with operating system counters.

Extended Events Concepts

Extended Events have a rich architecture, which consists of events, targets, actions, types, predicates, and maps. These artifacts are stored within a package, which is, in turn, stored within a module, which can be either a .dll or an executable. We discuss these concepts in the following sections.

Packages

A package is a container for the objects used within Extended Events. Here are the four types of SQL Server package:
  • Package0: The default package, used for Extended Events system objects.

  • Sqlserver: Used for SQL Server–related objects.

  • Sqlos: Used for SQLOS-related objects.

  • SecAudit: Used by SQL Audit; however, its objects are not exposed.

Events

An event is an occurrence of interest that you can trace. It may be a SQL batch completing, a cache miss, or a page split, or virtually anything else that can happen within the Database Engine, depending on the nature of the trace that you are configuring. Each event is categorized by channel and keyword (also known as category). A channel is a high-level categorization, and all events in SQL Server fall into one of the channels described in Table 20-1.
Table 20-1

Channels

Channel

Description

Admin

Well-known events with well-known resolutions. For example, deadlocks, server starts, CPU thresholds being exceeded, and the use of deprecated features.

Operational

Used for troubleshooting issues. For example, bad memory being detected, an AlwaysOn Availability Group replica changing its state, and a long I/O being detected are all events that fall within the Operational channel.

Analytic

High-volume events that you can use for troubleshooting issues such as performance. For example, a transaction beginning, a lock being acquired, and a file read completing are all events that fall within the Analytic channel.

Debug

Used by developers to diagnose issues by returning internal data. The events in the Debug channel are subject to change in future versions of SQL Server, so you should avoid them when possible.

Keywords, also known as categories, are much more fine grain. There are 100 categories within SQL Server 2022. These categories can be listed, by running the query in Listing 20-1.
SELECT DISTINCT map_value AS Category
FROM sys.dm_xe_map_values map
WHERE map.name = 'keyword_map'
ORDER BY map.map_value
Listing 20-1

Return List of Categories

Targets

A target is the consumer of the events; essentially, it is the device to which the trace data will be written. The targets available within SQL Server 2022 are detailed in Table 20-2.
Table 20-2

Targets

Target

Synchronous/Asynchronous

Description

Event counter

Synchronous

Counts the number of events that occur during a session

Event file

Asynchronous

Writes the event output to memory buffers and then flushes them to disk

Pair matching

Asynchronous

Determines if a paired event occurs without its matching event, for example, if a statement started but never completed

ETW*

Synchronous

Used to correlate Extended Events with operating system data

Histogram

Asynchronous

Counts the number of events that occur during a session, based on an action or event column

Ring buffer

Asynchronous

Stores data in a memory buffer, using first in first out (FIFO) methodology

*Event Tracking for Windows

Actions

Actions are commands that allow additional information to be captured when an event fires. An action is fired synchronously when an event occurs and the event is unaware of the action. There are 67 actions available in SQL Server 2022, which allow you to capture a rich array of information, including the statement that caused the event to fire, the login that ran this statement, the transaction ID, the CPU ID, and the call stack.

Predicates

Predicates are filter conditions that you can apply before the system sends events to the target. It is possible to create simple predicates, such as filtering statements completing based on a database ID, but you can also create more complex predicates, such as only capturing a long I/O that has a duration greater than five seconds, or only capturing the role change of an AlwaysOn Availability Group replica if it happens more than twice.

Predicates also fully support short-circuiting. This means that if you use multiple conditions within a predicate, then the order of predicates is important, because if the evaluation of the first predicate fails, the second predicate will not be evaluated. Because predicates are evaluated synchronously, this can have an impact on performance. Therefore, it is prudent to design you predicates in such a way that predicates that are least likely to evaluate to true come before predicates that are very likely to evaluate to true. For example, imagine that you are planning to filter on a specific database (with a database ID of 6) that is the target of a high percentage of the activity on the instance, but you also plan to filter on a specific user ID (MyUser), which is responsible for a lower percentage of the activity. In this scenario, you would use the WHERE (([sqlserver].[username]=N'MyUser') AND ([sqlserver].[database_id]=(6))) predicate to first filter out activity that does not relate to MyUser and then filter out activity that does not relate to database ID 6.

Types and Maps

All objects within a package are assigned a type. This type is used to interpret the data stored within the byte collection of an object. Objects are assigned one of the following types:
  • Action

  • Event

  • Pred_compare (retrieve data from events)

  • Pred_source (compare data types)

  • Target

  • Type

You can find a list of predicate comparators and predicate sources by executing the queries in Listing 20-2.
--Retrieve list of predicate comparators
SELECT name
        ,description,
    (SELECT name
                FROM sys.dm_xe_packages
                WHERE guid = xo.package_guid) Package
FROM sys.dm_xe_objects xo
WHERE object_type = 'pred_compare'
ORDER BY name ;
--Retrieve list of predicate sources
SELECT name
        ,description,
    (SELECT name
                FROM sys.dm_xe_packages
                WHERE guid = xo.package_guid) Package
FROM sys.dm_xe_objects xo
WHERE object_type = 'pred_source'
ORDER BY name ;
Listing 20-2

Retrieving Predicate Comparators and Sources

A map is a dictionary that maps internal ID values to strings that DBAs can understand. Map keys are only unique within their context and are repeated between contexts. For example, within the statement_recompile_cause context, a map_key of 1 relates to a map_value of Schema Changed. Within the context of a database_sql_statement type, however, a map_key of 1 relates to a map_value of CREATE DATABASE. You can find a complete list of mappings by using the sys.dm_xe_map_values DMV, as demonstrated in Listing 20-3. To check the mappings for a specific context, filter on the name column.
SELECT
        map_key
        , map_value
        , name
FROM sys.dm_xe_map_values ;
Listing 20-3

Sys.dm_xe_map_values

Sessions

A session is essentially a trace. It can contain events from multiple packages, actions, targets, and predicates. When you start or stop a session, you are turning the trace on or off. When a session starts, events are written to memory buffers and have predicates applied before they are sent to the target. Therefore, when creating a session, you need to configure properties, such as how much memory the session can use for buffering, what events can be dropped if the session experiences memory pressure, and the maximum latency before the events are sent to the target.

Creating an Event Session

You can create an event session using either the New Session Wizard, the New Session Dialog Box, or via T-SQL. We explore each of these options in the following sections. Before creating any event sessions, however, we first create the Chapter20 database, populate it with data, and create stored procedures, which we use in later examples. Listing 20-4 contains the script to do this.
--Create the database
CREATE DATABASE Chapter20 ;
GO
USE Chapter20
GO
--Create and populate numbers table
DECLARE @Numbers TABLE
(
        Number        INT
)
;WITH CTE(Number)
AS
(
        SELECT 1 Number
        UNION ALL
        SELECT Number + 1
        FROM CTE
        WHERE Number < 100
)
INSERT INTO @Numbers
SELECT Number FROM CTE;
--Create and populate name pieces
DECLARE @Names TABLE
(
        FirstName        VARCHAR(30),
        LastName        VARCHAR(30)
);
INSERT INTO @Names
VALUES('Peter', 'Carter'),
                 ('Michael', 'Smith'),
                 ('Danielle', 'Mead'),
                 ('Reuben', 'Roberts'),
                 ('Iris', 'Jones'),
                 ('Sylvia', 'Davies'),
                 ('Finola', 'Wright'),
                 ('Edward', 'James'),
                 ('Marie', 'Andrews'),
                 ('Jennifer', 'Abraham');
--Create and populate Customers table
CREATE TABLE dbo.Customers
(
        CustomerID           INT                NOT NULL        IDENTITY        PRIMARY KEY,
        FirstName            VARCHAR(30)        NOT NULL,
        LastName             VARCHAR(30)        NOT NULL,
        BillingAddressID     INT                NOT NULL,
        DeliveryAddressID    INT                NOT NULL,
        CreditLimit          MONEY              NOT NULL,
        Balance                 MONEY              NOT NULL
);
SELECT * INTO #Customers
FROM
         (SELECT
                 (SELECT TOP 1 FirstName FROM @Names ORDER BY NEWID()) FirstName,
                 (SELECT TOP 1 LastName FROM @Names ORDER BY NEWID()) LastName,
                 (SELECT TOP 1 Number FROM @Numbers ORDER BY NEWID()) BillingAddressID,
                 (SELECT TOP 1 Number FROM @Numbers ORDER BY NEWID()) DeliveryAddressID,
                 (SELECT TOP 1 CAST(RAND() * Number AS INT) * 10000
                 FROM @Numbers
                 ORDER BY NEWID()) CreditLimit,
                 (SELECT TOP 1 CAST(RAND() * Number AS INT) * 9000
                 FROM @Numbers
                 ORDER BY NEWID()) Balance
        FROM @Numbers a
        CROSS JOIN @Numbers b
) a;
INSERT INTO dbo.Customers
SELECT * FROM #Customers;
GO
CREATE INDEX idx_LastName ON dbo.Customers(LastName)
GO
CREATE PROCEDURE UpdateCustomerWithPageSplits
AS
BEGIN
        UPDATE dbo.Customers
        SET FirstName = cast(FirstName + replicate(FirstName,10) as varchar(30))
        ,LastName = cast(LastName + replicate(LastName,10) as varchar(30)) ;
END ;
GO
CREATE PROCEDURE UpdateCustomersWithoutPageSplits
AS
BEGIN
        UPDATE dbo.Customers
        SET CreditLimit = CreditLimit * 1.5
        WHERE Balance < CreditLimit - 10000 ;
END ;
GO
Listing 20-4

Creating the Chapter20 Database

Using the New Session Dialog Box

You can access the New Session dialog box from SQL Server Management Studio by first drilling through Management ➤ Extended Events in Object Explorer and then by selecting New Session from the Sessions context menu. We use the New Session dialog box to create a session that monitors page splits and correlates them with the stored procedures that caused them to occur. To allow this, we need to enable causality tracking, which gives each event an additional GUID value, called an ActivityID, and a sequence number; together, these allow the events to be correlated.

When you invoke the dialog box, the General page displays, as illustrated in Figure 20-1. On this page, you can specify a name for the session, choose whether or not it should start automatically after it is completed and automatically when the instance starts, whether the live data view launches after the session completes, and if causality tracking should be enabled.
Figure 20-1

The General page

Because we are going to monitor page splits, we name the session PageSplits and specify that the session should start automatically, both after creation and also when the instance starts. We also turn on causality tracking.

On the Events page, we first search for and select the page_splits and module_start events, as shown in Figure 20-2. The module_start event is triggered every time a programmable object fires.
Figure 20-2

The Events page

We now need to use the Configure button to configure each of the events. In the Global Fields (Actions) tab of the Configure screen, we select the nt_username and database_name actions for the module_start event, as illustrated in Figure 20-3.
Figure 20-3

The Global Fields (Actions) tab

Tip

If you need to configure the same actions for multiple events, you can multiselect the events.

On the Filter (Predicate) tab, we configure the page_splits event to be filtered on the database_name, which is Chapter20 in this case, as show in Figure 20-4. This means that only page splits relating to this database are captured. We do not filter the module_start event on the database_name, because the procedure that caused the page splits could, in theory, have been fired from any database.
Figure 20-4

The Filter (Predicate) tab

In the Event Fields tab of the Configure screen, the fields that relate to the event are displayed. If there are any optional fields, then we are able to select them. Figure 20-5 shows that we have selected the statement field for the module_start event.
Figure 20-5

The Event Fields tab

On the Data Storage page of the New Session dialog box, we configure the target(s). For our scenario, we configure a single event file target, as demonstrated in Figure 20-6. The parameters are context sensitive, depending on the type of target that you select. Because we have selected a file target, we need to configure the location and maximum size of the file. We also need to specify if we want new files to be created if the initial file becomes full, and if so, how many times this should happen.
Figure 20-6

The Data Storage page

On the Advanced page, we can specify the desired behavior in the event of memory pressure: whether single-event loss is acceptable, whether multiple-event loss is acceptable, or whether there should be no event loss at all. We can also set the minimum and maximum size for events and how memory partitioning should be applied. This is discussed in more detail in the following section. Additionally, we can configure dispatch latency. This indicates the maximum amount of time that an event remains in the buffers before it is flushed to disk.

Using T-SQL

You can also create event sessions via T-SQL using the CREATE EVENT SESSION DDL statement. The command accepts the arguments detailed in Table 20-3.
Table 20-3

Create Event Session Arguments

Argument

Description

event_session_name

The name of the event session that you are creating.

ADD EVENT | SET

Specified for every event that is added to the session, followed by the name of the event, in the format package.event. You can use the SET statement to set event-specific customizations, such as including nonmandatory event fields.

ACTION

Specified after each ADD EVENT argument if global fields should be captured for that event.

WHERE

Specified after each ADD EVENT argument if the event should be filtered.

ADD TARGET | SET

Specified for each target that will be added to the session. You can use the SET statement to populate target-specific parameters, such as the filename parameter for the event_file target.

The statement also accepts the WITH options, detailed in Table 20-4. The WITH statement is specified once, at the end of the CREATE EVENT SESSION statement.
Table 20-4

Create Event Session WITH Options

Option

Description

MAX_MEMORY

The maximum amount of memory that the event session can use for buffering events before dispatching them to the target(s).

EVENT_RETENTION_MODE

Specifies the behavior if the buffers become full. Acceptable values are ALLOW_SINGLE_EVENT_LOSS, which indicates that a single event can be can be dropped if all buffers are full; ALLOW_MULTIPLE_EVENT_LOSS, which indicates that an entire buffer can be dropped if all buffers are full; and NO_EVENT_LOSS, which indicates that tasks that cause events to fire are to wait until there is space in the buffer.

MAX_DISPATCH_LATENCY

The maximum amount of time that events can reside in the session’s buffers before being flushed to the target(s), specified in seconds.

MAX_EVENT_SIZE

The maximum possible size for event data from any single event. It can be specified in kilobytes or megabytes and should only be configured to allow events that are larger than the MAX_MEMORY setting.

MEMORY_PARTITION_MODE

Specifies where vent buffers are created. Acceptable values are NONE, which indicates that the buffers will be created within the instance; PER_NODE, which indicates that the buffers will be created for each NUMA node; and PER_CPU, which means that buffers will be created for each CPU.

TRACK_CAUSALITY

Specifies that an additional GUID and sequence number will be stored with each event so that events can be correlated.

STARTUP_STATE

Specifies if the session automatically starts when the instance starts. ON indicates it does, OFF indicates it does not.

Caution

Using the NO_EVENT_LOSS option for EVENT_RETENTION_MODE can cause performance issues on your instance, because tasks may have to wait to complete until there is space in the event session’s buffers to hold the event data.

The script in Listing 20-5 demonstrates how you can use T-SQL to create a session called LogFileIO. This session is similar to the Database Log File IO Tracking template, provided through the GUI. The difference is that we are additionally capturing the sqlos.wait_completed event and the sqlserver.DatabaseName global field, and filtering on this, so that only details of the Chapter20 transaction log are tracked.

The results of the trace will be written to a file called LogFilIO.xel in the C:Logs folder (which needs to be precreated). The STARTUP_SATATE option is used to start the session.
CREATE EVENT SESSION [LogFileIO] ON SERVER
ADD EVENT sqlos.async_io_completed(
    ACTION(sqlserver.database_name)
    WHERE ([sqlserver].[database_name]=N'Chapter20')),
ADD EVENT sqlos.async_io_requested(
    ACTION(sqlserver.database_name)
    WHERE ([sqlserver].[database_name]=N'Chapter20')),
ADD EVENT sqlos.spinlock_backoff(
    ACTION(sqlserver.database_name,sqlserver.sql_text)
    WHERE (([package0].[equal_uint64]([type],(85))) AND ([sqlserver].[database_name]=N'Chapter20'))),
ADD EVENT sqlos.wait_completed(
    ACTION(sqlserver.database_name)
    WHERE ([sqlserver].[database_name]=N'Chapter20')),
ADD EVENT sqlos.wait_info(
ACTION(sqlserver.client_app_name,sqlserver.database_name,sqlserver.is_system,sqlserver.session_id)
    WHERE ((([package0].[equal_uint64]([opcode],(1))) AND ([package0].[equal_uint64]([wait_type],(182)))) AND ([sqlserver].[database_name]=N'Chapter20'))),
ADD EVENT sqlserver.databases_log_flush(
    ACTION(sqlserver.database_name)
    WHERE ([sqlserver].[database_name]=N'Chapter20')),
ADD EVENT sqlserver.databases_log_flush_wait(
    ACTION(sqlserver.database_name)
    WHERE ([sqlserver].[database_name]=N'Chapter20')),
ADD EVENT sqlserver.file_write_completed(SET collect_path=(1)
    ACTION(sqlserver.database_name)
    WHERE (([package0].[equal_uint64]([file_id],(2))) AND ([sqlserver].[database_name]=N'Chapter20'))),
ADD EVENT sqlserver.file_written(SET collect_path=(1)
    ACTION(sqlserver.database_name)
    WHERE (([package0].[equal_uint64]([file_id],(2))) AND ([sqlserver].[database_name]=N'Chapter20')))
ADD TARGET package0.event_file(SET filename=N'C:LogsLogFileIO.xel',max_file_size=(512)),
ADD TARGET package0.histogram(SET filtering_event_name=N'sqlos.spinlock_backoff',source=N'sqlserver.sql_text'),
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)
GO
Listing 20-5

Creating an Event Session

Note

This session will start automatically, due to the STARTUP_STATE begin configured as ON.

Viewing the Collected Data

SQL Server provides a data viewer that you can use for basic analysis of event data from a file or live data from the buffers. For more complex analysis, however, you can access and manipulate the event data via T-SQL. The following sections discuss each of these methods of analysis.

Analyzing Data with Data Viewer

You can use the data viewer to watch live data as it hits the buffers by drilling through Management ➤ Extended Events ➤ Sessions in Object Explorer and selecting Watch Live Data from the Session context menu. Alternatively, you can use it to view data in the target by drilling through the session and selecting View Target Data from the Target context menu.

Tip

The data viewer does not support the ring buffer or ETW target types.

The script in Listing 20-6 inserts data into the Customers table in the Chapter20 database, which causes I/O activity for the transaction log, which is captured by our LogFileIO session.
USE Chapter20
GO
--Create and populate numbers table
DECLARE @Numbers TABLE
(
        Number        INT
)
;WITH CTE(Number)
AS
(
        SELECT 1 Number
        UNION ALL
        SELECT Number + 1
        FROM CTE
        WHERE Number < 100
)
INSERT INTO @Numbers
SELECT Number FROM CTE;
--Create and populate name pieces
DECLARE @Names TABLE
(
        FirstName        VARCHAR(30),
        LastName        VARCHAR(30)
);
INSERT INTO @Names
VALUES('Peter', 'Carter'),
                 ('Michael', 'Smith'),
                 ('Danielle', 'Mead'),
                 ('Reuben', 'Roberts'),
                 ('Iris', 'Jones'),
                 ('Sylvia', 'Davies'),
                 ('Finola', 'Wright'),
                 ('Edward', 'James'),
                 ('Marie', 'Andrews'),
                 ('Jennifer', 'Abraham');
--Insert to Customers
SELECT * INTO #Customers
FROM
         (SELECT
                 (SELECT TOP 1 FirstName FROM @Names ORDER BY NEWID()) FirstName,
                 (SELECT TOP 1 LastName FROM @Names ORDER BY NEWID()) LastName,
                 (SELECT TOP 1 Number FROM @Numbers ORDER BY NEWID()) BillingAddressID,
                 (SELECT TOP 1 Number FROM @Numbers ORDER BY NEWID()) DeliveryAddressID,
                 (SELECT TOP 1 CAST(RAND() * Number AS INT) * 10000
                 FROM @Numbers
                 ORDER BY NEWID()) CreditLimit,
                 (SELECT TOP 1 CAST(RAND() * Number AS INT) * 9000
                 FROM @Numbers
                 ORDER BY NEWID()) Balance
        FROM @Numbers a
        CROSS JOIN @Numbers b
        CROSS JOIN @Numbers c
) a;
INSERT INTO dbo.Customers
SELECT * FROM #Customers;
GO
Listing 20-6

Inserting into Customers

If we now open the data viewer for the event_file target under the LogFileIO session in Object Explorer, we see the results illustrated in Figure 20-7. The viewer shows each event and timestamp in a grid; selecting an event exposes the Details pane for that event.
Figure 20-7

Data view on event_file target

Notice that a data viewer toolbar is displayed in SQL Server Management Studio, as illustrated in Figure 20-8. You can use this toolbar to add or remove columns from the grid, as well as to perform grouping and aggregation operations.
Figure 20-8

Data viewer toolbar

Clicking the Choose Columns button invokes the Choose Columns dialog box. We use this dialog box to add the duration and wait_type columns to the grid, as shown in Figure 20-9.
Figure 20-9

The Choose Columns dialog box

We can now right-click the wait_type column, and select the Group By This Column option. This will cause all of the events to be rolled up, to the level of Wait Type.

We can now use the Aggregation button to invoke the Aggregation dialog box. We can use this dialog box to apply aggregate functions, such as SUM, AVG, or COUNT, to the data. It is also possible to sort the data by an aggregated value. Figure 20-10 shows that we are using this dialog box to add a SUM of the wait durations.
Figure 20-10

The Aggregation dialog box

In the data viewer grid, we are now able to see a SUM of the duration column for the wait_type, and if we expand this group, it displays the granular details, as shown in Figure 20-11.
Figure 20-11

The data viewer grid

Analyzing Data with T-SQL

If you require more complex analysis of the data, then you can achieve this via T-SQL. The sys.fn_xe_file_target_read_file function makes this possible by reading the target file and returning one row per event in XML format. The sys.fn_xe_file_target_read_file accepts the parameters detailed in Table 20-5.
Table 20-5

sys.fn_xe_file_target_read_file Parameters

Parameter

Description

path

The file path and file name of the .XEL file. This can contain the * wildcard so that rollover files can be included.

mdpath

The file path and name of the metadata file. This is not required for SQL Server 2012 and above but is for backward compatibility only, so you should always pass NULL.

initial_file_name

The first file in the path to read. If this parameter is not NULL, then you must also specify initial_offset.

initial_offset

Specifies the last offset that was read so that all events prior are skipped. If specified, then you must also specify initial_file_name.

The sys.fn_xe_file_target_read_file procedure returns the columns detailed in Table 20-6.
Table 20-6

sys.fn_xe_file_target_read_file Results

Column

Description

module_guid

The GUID of the module that contains the package

package_guid

The GUID of the package that contains the event

object_name

The name of the event

event_data

The event data, in XML format

file_name

The name of the XEL file that contains the event

file_offset

The offset of the block within the file that contains the event

Because the event data is returned in XML format, we need to use XQuery to shred the nodes into relational data. A full description of XQuery is beyond the scope of this book, but Microsoft provides an XQuery language reference on msdn.microsoft.com.

The script in Listing 20-7 runs the UpdateCustomersWithPageSplits and UpdateCustomersWithoutPageSplits procedures in the Chapter20 database before extracting the event data using the sys.fn_xe_file_target_read_file. We then use the XQuery Value method to extract relational values from the XML results. Finally, because we have turned on causality tracking, we group the data by the correlation GUID to see how many page splits each stored procedure caused. UpdateWithoutPageSplits provides a contrast.

Tip

Remember to update filepaths to match your own configuration before running the query.

--Run the update procedures
EXEC UpdateCustomersWithoutPageSplits ;
GO
EXEC UpdateCustomerWithPageSplits ;
GO
--Wait 30 seconds to allow for the XE buffers to be flushed to the target
WAITFOR DELAY '00:00:30' ;
--Query the XE Target
SELECT c.procedurename, d.pagesplits
 FROM
 (
        SELECT
                correlationid,
                COUNT(*) -1 PageSplits -- -1 to remove the count of the module_start event
        FROM
        (
               SELECT CapturedEvent,
                        xml_data.value('(/event/data[@name=''object_name'']/value)[1]', 'nvarchar(max)') procedurename,  --extract procedure name
                        xml_data.value('(/event/action[@name=''attach_activity_id'']/value)[1]', 'uniqueidentifier') correlationid --extract Correlation ID
                FROM
                 (
--Query the fn_xe_file_target_read_file function, to extract the raw XML
                                SELECT
                                OBJECT_NAME CapturedEvent,
                                CAST(event_data AS XML) xml_data
                                FROM
sys.fn_xe_file_target_read_file('C:mssqlpagesplits*.xel', NULL , NULL, NULL) as XE ) a
                ) b
                GROUP BY correlationid
        ) d
INNER JOIN --Self join, to allow the count of page splits
(
        SELECT CapturedEvent,
                xml_data.value('(/event/data[@name=''object_name'']/value)[1]', 'nvarchar(max)') procedurename,
                xml_data.value('(/event/action[@name=''attach_activity_id'']/value)[1]', 'uniqueidentifier') correlationid
        FROM
         (
                SELECT object_name CapturedEvent,
                CAST(event_data AS XML) xml_data
                FROM
                sys.fn_xe_file_target_read_file('C:mssqlpagesplits*.xel', NULL , NULL, NULL) as XE ) a
        ) c
ON c.correlationid = d.correlationid
        AND c.procedurename IS NOT NULL ;
Listing 20-7

Analyzing Event Data with T-SQL

Tip

Using XQuery allows you to query on every event field and action that is captured within your trace, so you can create very complex queries, providing rich and powerful analysis of the activity within your instance.

Correlating Extended Events with Operating System Data

Extended Events offer the capability to integrate with operating system–level data. This gives useful insights, such as the queries that were running when CPU spiked, etc. The following sections discuss how to correlate SQL Server events with Perfmon data and other operating system–level events.

Correlating Events with Perfmon Data

Before Extended Events were introduced, DBAs used a tool called SQL Trace and its GUI, Profiler, to capture traces from SQL Server; it was possible to correlate this data with data from Perfmon. With Extended Events, you do not often need to make this correlation, because Extended Events include Perfmon counters for processor, logical disk, and system performance objects, such as context switches and file writes. Therefore, you can correlate SQL Server events with operating system counters by adding these objects to the session and by following the T-SQL analysis techniques discussed in the previous section.

Tip

Perfmon counters are in the Analytic channel but have no category.

The script in Listing 20-8 demonstrates creating an event session that captures statements executed within the instance, alongside processor counters. Processor counters are captured every 15 seconds for each processor in the system. The results are saved to an event file target and an ETW target.
CREATE EVENT SESSION Statements_with_Perf_Counters
ON SERVER
--Add the Events and Actions relating to each Event
ADD EVENT sqlserver.error_reported(
    ACTION(sqlserver.client_app_name,sqlserver.database_id,sqlserver.query_hash,sqlserver.session_id)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND
[package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.module_end(SET collect_statement=(1)
    ACTION(sqlserver.client_app_name,sqlserver.database_id,sqlserver.query_hash,sqlserver.session_id)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND
[package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.perfobject_processor,
ADD EVENT sqlserver.rpc_completed(
    ACTION(sqlserver.client_app_name,sqlserver.database_id,sqlserver.query_hash,sqlserver.session_id)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND
[package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sp_statement_completed(SET collect_object_name=(1)
    ACTION(sqlserver.client_app_name,sqlserver.database_id,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_batch_completed(
    ACTION(sqlserver.client_app_name,sqlserver.database_id,sqlserver.query_hash,sqlserver.session_id)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND
[package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_statement_completed(
    ACTION(sqlserver.client_app_name,sqlserver.database_id,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND
[package0].[equal_boolean]([sqlserver].[is_system],(0))))
--Add the Targets
ADD TARGET package0.event_file(SET filename=N'C:MSSQLStatementsAndProcessorUtilization.xel'),
ADD TARGET package0.etw_classic_sync_target(SET default_etw_session_logfile_path=N'C:MSSQLStatementsWithPerfCounters.etl')
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF) ;
GO
--Start the instance
ALTER EVENT SESSION Statements_with_Perf_Counters
ON SERVER
STATE = start;
Listing 20-8

Creating an Event Session with Perfmon Counters

Tip

The SQL Server service account must be in the Performance Log Users group, or an error is thrown.

Integrating Event Sessions with Operating System–Level Events

Note

To follow the demonstrations in this section, you need to install Windows Performance Toolkit, which you can download from msdn.microsoft.com as part of the Windows Deployment and Assessment Toolkit.

There are instances in which you may need to integrate event session data with operating system data other than Perfmon counters that SQL Server provides. For example, imagine a scenario in which you have an application that exports SQL Server data to flat files in the operating system so that a middleware product, such as BizTalk, can pick them up. You are having trouble generating some files and you need to view the process flow—from SQL statement being run through to the WMI events being triggered in the operating system. For this, you need to merge event session data with a trace of WMI events. You can achieve this through the ETW (Event Tracking for Windows) architecture.

To demonstrate this, we first create an event trace session in Performance Monitor using the WMI provider, and then we integrate it with the event session that we created in the previous section. (You can find Performance Monitor in Administrative Tools in Windows.) After we open Performance Monitor, we select New ➤ Data Collector Set from the Event Trace Sessions context menu, which causes the Create New Data Collector Set wizard to be invoked. On the first page of the wizard, specify a name for the Collector Set, as illustrated in Figure 20-12, and specify if the Data Collector set should be configured manually or based on a template. In our scenario, we choose to configure it manually.
Figure 20-12

The Create New Data Collector Set wizard

On the page for enabling event trace providers, we can use the Add button to add the WMI-Activity provider, as illustrated in Figure 20-13.
Figure 20-13

Add the WMI provider

We now use the Edit button to invoke the Properties dialog box. Here, we add the Trace and Operational categories by using the check boxes, as shown in Figure 20-14.
Figure 20-14

Properties dialog box

After exiting the Properties dialog box, we move to the next page of the wizard, where we can configure the location where the trace file is stored. We configure the trace file to be saved to the same location as our event session trace, as shown in Figure 20-15.
Figure 20-15

Configure the trace file location

On the final page of the wizard, we leave the default options of running the trace under the default account and then save and close the trace.

In Performance Monitor, our trace is now visible in the Event Trace Sessions folder, but showing as stopped. We can use the context menu of the trace to start the Data Collector Set, as shown in Figure 20-16. Also notice that there is a Data Collector Set called XE_DEFAULT_ETW_SESSION. Our extended event session created this because we created an ETW target. This session is required for integrating the data.
Figure 20-16

Start the Data Collector Set

Now that both the WMISession and Statements_with_Perf_Counters sessions are started, we use the BCP command in Listing 20-9 to generate activity, which causes events to fire in both sessions.
bcp chapter20.dbo.customers out c:mssqldump.dat -S .PROSQLADMIN -T -c
Listing 20-9

Generating Activity

We now need to ensure that the buffers of both sessions are flushed to disk. We do this by stopping both sessions. After stopping the Statements_with_Perf_Counters session, we also need to stop the XE_DEFAULT_ETW_SESSION ETW session in Performance Monitor. You can stop the Statements_with_Perf_Counters session by using the T-SQL command in Listing 20-10.
ALTER EVENT SESSION Statements_with_Perf_Counters
ON SERVER
STATE = stop;
Listing 20-10

Stopping the Event Session

You can stop the WMISession and XE_DEFAULT_ETW_SESSION by selecting Stop from their respective context menus in Performance Monitor.

The next step is to merge the two trace files together. You can achieve this from the command line by using the XPERF utility with the -Merge switch (demonstrated in Listing 20-11). This command merges the files together, with StatementsWithPerfCounters.etl being the target file. You should navigate to the C:Program Files (x86)Windows Kits8.1Windows Performance Toolkit folder, before running the script.
xperf -merge c:mssqlwmisession.etl C:MSSQLStatementsWithPerfCounters.etl
Listing 20-11

Merging Trace Files

Now that all events are in the same file, you can open and analyze this .etl file with Windows Performance Analyzer, which is available as part of the Windows Performance Toolkit, as shown in Figure 20-17. Once installed, you can access Windows Performance Analyzer via the Windows Start menu. A full discussion of Windows Performance Analyzer is beyond the scope of this book, but you can find it in Administrative Tools in Windows after it’s installed. You will find full documentation on msdn.microsoft.com.
Figure 20-17

Windows Performance Analyzer

Summary

Extended Events introduce new concepts that you must understand in order to fully harness their power. Events are points of interest that are captured in a trace, whereas actions provide extended information, in addition to the event columns. Predicates allow you to filter events in order to provide a more targeted trace, and targets define how the data is stored. A session is the trace object itself, and it can be configured to include multiple events, actions, predicates, and targets.

You can create an event session through the New Session Wizard, an easy and quick method that exposes Templates; via the New Session dialog box; or of course, via T-SQL. When creating a session via T-SQL, you use the CREATE EVENT SESSION DDL statement to configure all aspects of the trace.

Each Extended Event artifact is contained within one of four packages: Package0, Sqlserver, Sqlos, and SecAudit. The contents of SecAudit are not exposed, however, since these are used internally to support SQL Audit functionality, which is discussed in Chapter 11.

You can view data using the data viewer. The data viewer allows you to watch live data in the session’s buffers, and it also supports viewing target data from the Event File, Event Count, and Histogram Target types. The data viewer provides basic data analysis capability, including grouping and aggregating data.

For more complex data analysis, you can open targets in T-SQL. To open an Event File target, use the sys. fn_xe_file_target_read_file results system stored procedure. You then have the power of T-SQL at your disposal for complex analysis requirements.

You can correlate events by turning on causality tracking within the session. This adds a GUID and a sequence number to each event so that you can identify relationships. You can also easily correlate SQL events with Perfmon data, because Extended Events expose processor, logical disk, and system performance counters. To correlate events with other operating system–level events, event sessions can use the ETW target, which you can then merge with other data collector sets to map Extended Events to events from other providers in the ETW architecture.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.135.129