4.2.5 Filters
Filters are also known as predicates in
the context of Extended Events, and both terms accurately describe
their purpose, as they act like a where
clause when a session is defined such that only events that meet
certain criteria have their actions performed. For example, you may
only want data to be collected when an event happens in the context of
a specific database or when a specific user executed the query that
caused the event. Although these may seem like reasonably high-level
conditions on which to filter, you would be correct to assume that with
Extended Events they can be a lot more technical, as you’ll see in a
moment.
Filters can delve deep into a database’s internal
objects, as well as a SQL Server instance’s and query’s runtime
properties. For that reason, the most common filters you’ll likely
start using are for a query’s runtime duration, the lock mode taken, or
the object ID affected by the event. Defined filters must always
evaluate as a Boolean expression; meaning you should focus on using the
usual =, >, <, and <> operators.
Following are some examples of filters you might define for your sessions:
The complete list of available filters, or predicate sources, as you’ll see them referred to, is available by querying a DMV as shown here:
select name, description from sys.dm_xe_objects where object_type = 'pred_source'
If you’re beginning to use Extended
Events instead of Profiler, these filters are the ones you are likely
to initially want to use; however, some filters contain internal logic
that wasn’t available in Profiler. For example, you can set a session
to count how many times an event it monitors for occurs, and only
perform an action every n
occurrences of the event. This might be useful for something that
happens so often that it’s not practical to log every occurrence, but
you still want to monitor it.
Finally, the way in which filters are evaluated
is also more efficient than what you might be used to with other tools,
as the objective is always to limit the overhead of using Extended
Events as much as possible. Although filters are evaluated each time
their associated events occur, they don’t have to add significant
overhead to the user’s query execution time if they’re written
optimally. Extended Events use a method known as short circuiting
to evaluate a session’s filters. This means each part of the filter’s
definition is put in an ordered list, and each item in the list is
evaluated only if the previous item evaluated to true.
Therefore, if the most selective items in the filter are defined first,
most of the filter may never need to be evaluated until necessary. This
is very different from traditional SQL Server select queries, for which
each part of the where clause is
evaluated and included in the query plan before execution, regardless
of the value it might actually bring to the query.
4.26 Targets
A target
is the destination for all the information you can capture with
Extended Events. However, whereas the terminology used so far has been
fairly straightforward, now you start to see some terms that are less
self-explanatory. In fact, it may be these terms you’ve seen in the
past that made you think twice about using the feature. Fortunately,
the SSMS interface hides some of the complexity from us.
Event Files
Event files, like their name suggests,
are flat files that reside on an operating system drive and to which
event data is written. They remain there until you delete them
manually. The event files themselves have a default file extension of .xel
and store data in a binary format that isn’t human-readable without a
tool such as SQL Server Management Studio. Fortunately, SSMS can open
these files even if they were captured on another server. It can also
export the data to a database table or a CSV file, making the data more
portable if needed.
When an Extended Events session is configured to
use an event file as a target, the event data is first written by the
Extended Events engine to memory buffers before a second process writes
it from memory to disk. This separation of processes is an important
difference between Extended Events and other troubleshooting tools, as
it prevents the physical writing of the data to disk from affecting
performance for end users under normal circumstances. This behavior
explains why event files are considered asynchronous targets.
Because Extended Events has been designed for use
on servers with even the heaviest of workloads, there are several
options you can configure regarding how the data is buffered and what
should occur when the buffer is overwhelmed. The next three settings
reviewed, memory buffer size, event retention, and maximum dispatch
latency, apply to most of the targets Extended Events sessions can use,
but it is useful to consider them now that you understand the potential
problems a session with a full memory buffer and an event file target
could have.
It’s worth mentioning that the path and filename
you specify when you create a session must exist otherwise the session
won’t start. It’s often useful to create your own directory for
Extended Events files, and then make sure SQL Server can read and write
to it.
Memory Buffer Size
The size of the memory buffer is a
configurable session option that can ultimately determine how much of a
performance impact an Extended Events session has on your server, and
potentially how much event data you might lose in busy conditions. For
a small server with a small workload, the default maximum buffer size
of 4MB is probably sufficient; but on a much busier server, you might
be writing more event data to the memory buffer than your target can
subsequently flush to its storage during peak periods.
As a hypothetical example, if your Extended
Events session is capturing event data at the rate of 200MB/sec, but
your server can only write 100MB/sec to disk, you’re very quickly going
to either need a lot of memory to store events before they’re flushed
to disk or begin discarding data from the buffer. The buffer is a First
in, First out (FIFO) list, so if unflushed events need to be deleted to
make room for newer events, then the oldest ones will be removed first.
That example should explain why you might choose
to configure your session to use more memory, based upon your
preference for what should happen if the buffer ever fills up, and
therefore, how much event data you’re willing to lose in order to
maintain system performance for users. Exactly what events are dropped
is determined by the Event Retention option.
Event Retention
What should happen if the memory buffer
ever fills up is also a configurable session option, known as Event
Retention. Three options determine how SQL Server should respond when
the memory buffer is full and a session tries to write event data to it:
- no event loss — This option
is the strictest of the possible settings and is not recommended for
production environments. This setting means if the memory buffer ever
fills up, end user queries must wait until there is free space in the
memory buffer for their event data to be written to before they are
allowed to continue. It’s very similar to how SQL Trace works in that
event data is never lost, but the consequences of guaranteeing that
complete set of event data on a busy system can be disastrous.
- single event loss — This is
the default when you create an Extended Events session. It instructs
SQL Server that losing individual events is acceptable if it means the
end user’s query performance won’t be affected like it would be with
the no event loss option.
Because the memory buffer is a FIFO list, the oldest event in the
buffer is deleted to make room for the latest system activity. Although
events are removed one at a time, if the Extended Events engine needs
to write 500 new events to the buffer, it may have to delete the 500
oldest events first. While this sounds like a good compromise, it won’t
protect you from having an undersized memory buffer on a busy system,
as ultimately the amount of data you lose will render your captured
data worthless.
- multiple event loss — This
tells SQL Server to favor protecting query performance at the expense
of capturing event data on a massive scale. If the memory buffer is
overwhelmed by incoming events, it can decide to completely empty the
buffer rather than delete events one by one to maintain query
performance. While this might mean you lose your event data, it’s a
good fail-safe option to have in place if you ever deploy a session on
a busy server for the first time and not know what its event generation
rate is likely to be.
Maximum Dispatch Latency
Now that you’ve seen how crucial it is
to have adequate space in the memory buffer used by the Extended Events
engine, you can understand why there are various options that determine
what should happen if it fills up. Of course, the best solution is to
ensure that it never fills up. There are two options for this: setting
a very large memory buffer size or configuring the maximum dispatch
latency.
If an asynchronous target is being used, it’s
possible that events aren’t transferred from the memory buffer to the
target until either the session stops and flushes the buffer, or there
is memory buffer pressure that forces a flush. This shouldn’t usually
be a problem, but you might think it’s good to keep as much free space
in the memory buffer as possible in case of sudden system activity that
generates a lot of event data.
This is where you can use the Maximum Dispatch
Latency setting to specify the maximum amount of time event data can
stay in the memory buffer before it is flushed to the target. The
default is 30 seconds, which for a session with a properly sized memory
buffer should be more than adequate; there’s no need to change any of
the default settings unless necessary. However, if you want to be
cautious you can lower the maximum dispatch latency value; the minimum
accepted value is 1 second.