对于接纳扩展事件,其中一个最大的障碍就是要对XML和XQuery有一定的了解以便分析数据。我们可以使用T-SQL来完成创建和运行会话,但是不管会话的存在目的是什么,数据都被编译成XML。但是从SQL 2012开始就去除了这种限制。我们通过
上一文中介绍的,可以用GUI对扩展事件进行创建和管理,同样,在本文中,我们演示如何在SSMS GUI中查看的操作捕获的结果数据。
查看数据:
当创建和启用扩展事件会话之后,有两种方式可以查看事件数据:Live data viewer和target data viewer。为了演示需要,下面快速创建一个XE_SampleCapture事件会话。这个事件涉及批处理(batch)、语句(statement)和存储过程(sp)的执行情况,主要包含:
- query_hash:使用相似逻辑但独立计划的方式标识查询
- query_plan_hash:标识具有相同操作树结构的独立计划
这些字段分别与
查询指纹和计划指纹相关。使用这两列主要用于分析ad-hoc(即席查询)的工作负载。查找一些非常类似的语句差异,比如拼接字符串中的不同值。事件会话代码如下:
CREATE EVENT SESSION [XE_SampleCapture] ON SERVER
ADD EVENT sqlserver.rpc_completed (
ACTION ( sqlserver.database_id, sqlserver.query_hash,
sqlserver.query_plan_hash )
WHERE ( [sqlserver].[is_system] = ( 0 ) ) ),
ADD EVENT sqlserver.sp_statement_completed ( SET collect_statement = ( 1 )
ACTION ( sqlserver.database_id, sqlserver.query_hash,
sqlserver.query_plan_hash )
WHERE ( [sqlserver].[is_system] = ( 0 ) ) ),
ADD EVENT sqlserver.sql_batch_completed (
ACTION ( sqlserver.database_id, sqlserver.query_hash,
sqlserver.query_plan_hash )
WHERE ( [sqlserver].[is_system] = ( 0 ) ) ),
ADD EVENT sqlserver.sql_statement_completed (
ACTION ( sqlserver.database_id, sqlserver.query_hash,
sqlserver.query_plan_hash )
WHERE ( [sqlserver].[is_system] = ( 0 ) ) )
ADD TARGET package0.event_counter,
ADD TARGET package0.event_file ( SET filename = N'D:\temp\XE_SampleCapture' ,
max_file_size = ( 512 ) ),
ADD TARGET package0.histogram ( SET filtering_event_name = N'sqlserver.sql_statement_completed' ,
slots = ( 16 ) ,
source = N'sqlserver.database_id' ),
ADD TARGET package0.ring_buffer ( SET max_events_limit = ( 10000 ) ,
max_memory = ( 4096 ) )
WITH ( MAX_MEMORY = 16384 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
Live data viewer(监控实时数据):
这个功能(下面第一个图所示)不管是目标被选中或者会话不存在对应目标时都可用,它显示了需要收集的事件的简要内容。打开【监控实时数据】并运行上面的脚本,可以看到下面第二个图的情况:
默认情况下是没数据的,当脚本执行时,就开始有数据收集。但是注意,前面提到过“调度延时(dispatch latency)”,一旦延时达到或者中间缓存区被填充,那么界面就会开始显示事件的数据。
调度延时和内存缓存区:
扩展事件引擎把事件数据流先写入中间内存缓存区。调度延时是会话级别的配置,定义了频率(秒为单位),然后事件数据从内存刷新到目标展示中。
需要注意的是,在监控实时数据界面的结果并不保存,除非你导出数据。但是这个导出操作需要停止事件显示之后才可以(SSMS左上角的红色方框),然后按下图方式导出对应格式:
对于停止数据馈送或关闭查看器可以随时进行,同时,如果SQL Server认为查看器会影响性能,会自动断开连接。
Target data viewer(查看目标数据):
查看活动会话数据的另外一个方法是右键特定的目标,选择【查看目标数据】,如下图:
如果事件中有“event_file”目标如上图,可以查看已经被写入硬盘文件的事件数据。这些数据不会刷新,仅仅显示截至你打开查看器时候的事件数据。
对于一个“event_file”目标,相对于“监控实时数据”而言有一个好处,就是不需要要求SQL Server把数据流加载到SSMS或者目标中,只是读取目标中已经存储的数据。
存储在“event_file”目标中的事件数据可以在事件会话停止之后查看,因为数据已经固化在硬盘的.xel文件中。可以把.xel文件拖拽到SSMS或其他方式在SSMS中打开。“system_health”事件的.xel文件路径在默认error log文件夹。
直接打开.xel文件的结果和“监控实时数据”查看器、“目标查看器”看上去基本一样,除了窗口名不同。窗口名是显示.xel文件的名字,而不是其他两者一样以“event_file”为后缀。
从目标数据中查看ring_buffer目标:
当查看“ring_buffer”目标时,使用查看目标数据功能并不能很好地展示,因为整个XML文档以链接的方式显示。
当需要分析数据时,要使用XQuery。
查看“event_counter”、“histogram”和“pair_matching”目标:
最后三个目标:event_counter”、“histogram”和“pair_matching”,只能使用目标查看器或XQuery来查看或分析数据,在我们的XE_SqmpleCapture会话事件中,或其他带有“histogram”目标的事件会话,右键这个目标,然后用查看目标数据来查看:
可以通过右键选择刷新频率来刷新数据:
这三个目标数据都存储在内存中,一旦你停止事件会话,数据就会释放,然后事件数据查看器的数据就会消失。如果想保存这些数据,需要使用下图的右键选择【复制】功能,或者选择【导出至CSV】,提醒一下,只要不关闭这个界面或者点刷新,那么这三个目标的数据还是会在查看器中可供使用。
显示选项:定制列
在每一个查看器中,都可以定制化需要显示的列。默认情况下仅显示事件的“name”和“timestamp”,这两个列是唯一适合所有事件的数据列。当选择任何一行数据时,下方的【详细信息】框会显示对应对应的事件收集列。如果要显示某一额外列,可以【详细信息】中的对应的行,选择【选择表中的列】,比如下图,选择【duration】列之后,就显示出来了。
可以重复这个步骤直到所需列全部显示为止。除此之外,可以用另外一种方式选择:
关于定制列,还有一个技巧,就是创建一个基于两列或多列的新列,在对于存储在不同字段的文本捕获事件而已非常有用。比如,对于“sp_statement_completed”实现中的“statement”列存储查询文本,而“batch_completed”事件使用“batch_text”列来存储文本。如果把这两个列都显示出来,你会发现batch_completed中的statement列总为NULL,而相对的sp_statement_completed事件的batch_text也总为NULL:
这种数据存在不同的列中的事件在分析过程中会带来很大的影响,可以通过合并来分析可以缓解这种问题(但是由于不不确定全部解决,所以这里不使用解决而使用缓解)。在【选择列】选项中,通过右下角的【新建】按钮,然后选择需要合并的列,并赋予新列名:
可以看到新的列已经合成。不过注意这个列仅仅是合并字符串,如果是合并非字符串数据类型,显示结果可能不是所要的。比如你尝试合并logical_reads和database_id时,仅显示logical_reads。
一旦新的定制列完成,可以保存配置。用下面两图的方式均可:
文件会以.viewsetting后缀名保存,然后在后续使用的时候,用同样的选项把文件加载进去即可。
分析数据:
各种查看器提供了查看数据的GUI界面,但是和Profiler的GUI不同(仅能排序列和过滤数据),扩展事件查看器可以免去把数据加载到表或者使用第三方工具查看的麻烦。
排序:
排序是对事件数据的最简单操作方式之一,选择需要排序的列,然后右键即可选择升序还是降序排列,也可以通过单击列来实现。这个对筛选【duration】/逻辑读写等列时很有用。
过滤:
使用【筛选器】按钮可以过滤查看器中的数据。可以对日期、时间列进行范围过滤,包括事件的全局字段。除此之外还可以创建复杂的过滤条件,类似事件会话中的谓词,通过AND/OR或者(=,<>,Like,Not Like,Null等):
过滤后得到的新结果也同样可以另存为一个新的.xel文件。对于源文件,重新打开后,筛选器依旧生效。因此应该养成每次打开文件都要检查事件数量的习惯:
合并.xel文件:
在某些情况下,我们需要合并多个.xel文件进行分析,比如要侦测AlwaysON中多个节点的故障,可能需要在每个节点使用扩展事件收集文件,然后合并.xel文件进行分析。通过下图方式打开多个文件:
点击【确定】之后,将会在一个界面中显示合并后的数据,此时可以把新结果另存为一个新的.xel文件。
搜索:
Profiler 界面也提供搜索功能,在搜索特定字符文本时很有用。扩展事件查看器提供了同样的功能,使用界面中的望远镜按钮即可:
可以搜索存在于显示列中的列。如果没有添加新列,默认只会查找“name”和“Timestamp”列。搜索功能很常用,这里就不累赘。
标记行:
一旦找到感兴趣的数据,可以在查看器中使用标记(bookmark)功能,高亮对应的行,右键→【切换书签】
标记后的样子:
通过添加书签,可以快速在大量数据中切换和定位行。可以用同样的方式取消标记,如果需要取消全部标记,选择下图的【清除所有书签】:
分组:
虽然合并列、筛选数据和查找特定值在分析事件数据时很有用,但是对于分析趋势或异常却没什么帮助。通过【分组】功能却可以有所帮助,这一点是Profiler所不能企及的。
在对数据进行分组之后,如下图方式,会发现展示界面已经变化:
常用于分组的列有:
- event(事件名)
- object_name或者object_id
- database_name或database_id
- 登录列(如username,nt_username)
- client_app_name
- client_hostname
但是对于【duration】、【logical_reads】和【CPU】这类列进行分组反而用处不大。虽然这些都是事件的指标。这些值更适合筛选而不是分组。然而对文本类的列进行分组又是一个不错的选择,这样可以看出最常被执行的语句及其频率。
遗憾的是,扩展事件没有办法对文本数据进行格式整理,如果你尝试分组【statement】或【batch_text】时,你会发现会有很多总数只有1行的语句(因为语句可能会有很多小差异,但是本质上是一句)。
相比之下,对query_hash或query_plan_hash列进行分组(使用的是SQL 2008出现的sys.dm_exec_query_stats DMV)会更加清晰。
聚合:
GUI的最后一个分析工具就是聚合(Aggregation)。这个要求最少对一列进行聚合之后才可用,对于非数值型数据也有所限制(比如batch_text、database_id、xml_report等)只有COUNT聚合。对于数值型列,可以进行SUM/MIN/MAX/AVG。
还可以对聚合列进行排序:
还可以对不同的列进行不同的聚合操作。
总结:
从SQL 2012开始的GUI界面,提供了很多很好的分析功能,使得用户不再强制使用T-SQL和XQuery来分析数据,使得收集的数据更有价值和易用。
下一节是目前系列的最后一问,如作者继续发布,本人也将继续翻译:
- SQL Server 扩展事件(Extented Events)从入门到进阶(4)——扩展事件引擎——基本概念