前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如果正确读取SQL Server中的扩展事件?

如果正确读取SQL Server中的扩展事件?

作者头像
全栈程序员站长
发布2022-07-11 17:57:07
3.3K0
发布2022-07-11 17:57:07
举报
文章被收录于专栏:全栈程序员必看

SQL Server中使用扩展事件捕捉所需的信息后,可以选择存放的位置。比如说内存或文件中,但无论存在哪里,其本质都是一个大XML。因此在SQL Server中读取该XML就是解析扩展事件结果的方式。

微软官方或者一些SQL Server论坛提供了使用SQL XML解析扩展事件的脚本,如代码清单1所示。

代码语言:javascript
复制
   1: WITH    events_cte
代码语言:javascript
复制
   2:           AS ( SELECT   DATEADD(mi,
代码语言:javascript
复制
   3:                                 DATEDIFF(mi, GETUTCDATE(), CURRENT_TIMESTAMP),
代码语言:javascript
复制
   4:                                 xevents.event_data.value('(event/@timestamp)[1]',
代码语言:javascript
复制
   5:                                                          'datetime2')) AS [event time] ,
代码语言:javascript
复制
   6:                                                             xevents.event_data.value('(event/@name)[1]',
代码语言:javascript
复制
   7:                                                  'nvarchar(128)') AS [Event Name],
代码语言:javascript
复制
   8:                         xevents.event_data.value('(event/action[@name="client_app_name"]/value)[1]',
代码语言:javascript
复制
   9:                                                  'nvarchar(128)') AS [client app name] ,
代码语言:javascript
复制
  10:                         xevents.event_data.value('(event/action[@name="client_hostname"]/value)[1]',
代码语言:javascript
复制
  11:                                                  'nvarchar(max)') AS [client host name] ,
代码语言:javascript
复制
  12:                         xevents.event_data.value('(event/action[@name="sql_text"]/value)[1]',
代码语言:javascript
复制
  13:                                                  'nvarchar(max)') AS [sql_text] ,
代码语言:javascript
复制
  14:           
代码语言:javascript
复制
  15:                         xevents.event_data.value('(event/action[@name="database_name"]/value)[1]',
代码语言:javascript
复制
  16:                                                  'nvarchar(max)') AS [database name] ,
代码语言:javascript
复制
  17:                         xevents.event_data.value('(event/action[@name="username"]/value)[1]',
代码语言:javascript
复制
  18:                                                  'nvarchar(max)') AS [username] ,
代码语言:javascript
复制
  19:                         xevents.event_data.value('(event/action[@name="duration"]/value)[1]',
代码语言:javascript
复制
  20:                                                  'bigint') AS [duration (ms)] ,
代码语言:javascript
复制
  21:                         xevents.event_data.value('(event/action[@name="cpu_time"]/value)[1]',
代码语言:javascript
复制
  22:                                                  'bigint') AS [cpu time (ms)] ,
代码语言:javascript
复制
  23:                         xevents.event_data.value('(event/data[@name="object_name"]/value)[1]',
代码语言:javascript
复制
  24:                                                  'nvarchar(max)') AS [OBJECT_NAME]
代码语言:javascript
复制
  25:                FROM     sys.fn_xe_file_target_read_file('D:\XeventResutl\DDLAudit*.xel',
代码语言:javascript
复制
  26:                                                         NULL, NULL, NULL)
代码语言:javascript
复制
  27:                         CROSS APPLY ( SELECT    CAST(event_data AS XML) AS event_data
代码语言:javascript
复制
  28:                                     ) AS xevents
代码语言:javascript
复制
  29:              )
代码语言:javascript
复制
  30:     SELECT  *
代码语言:javascript
复制
  31:     FROM    events_cte
代码语言:javascript
复制
  32:     ORDER BY [event time] DESC;

代码清单1.读取扩展事件文件的脚本

但代码清单1的脚本使用的是XQuery,XQuery在使用Xml的节点属性作为删选条件时,数据上千以后就会变得非常慢。因此我对上述脚本进行了改写,将XML读取出来后,变为节点的集合以关系数据格式存放,再用子查询进行筛选,这种方式读取数据基本上是秒出,如代码清单2所示。

代码语言:javascript
复制
   1: WITH   tt
代码语言:javascript
复制
   2:          AS ( SELECT   MIN(event_name) AS event_name ,
代码语言:javascript
复制
   3:               DATEADD(hh,DATEDIFF(hh, GETUTCDATE(), CURRENT_TIMESTAMP),
代码语言:javascript
复制
   4:                                CONVERT(DATETIME, MIN(CASE WHEN d_name = 'collect_system_time'
代码语言:javascript
复制
   5:                                                          AND d_package IS NOT NULL THEN d_value
代码语言:javascript
复制
   6:                                                      END))) AS [event_timestamp] ,
代码语言:javascript
复制
   7:                        CONVERT 
代码语言:javascript
复制
   8:        (VARCHAR(MAX), MIN(CASE WHEN  d_name = 'client_hostname'
代码语言:javascript
复制
   9:                                     AND d_package IS NOT NULL THEN d_value
代码语言:javascript
复制
  10:                           END)) AS [Client_hostname] ,
代码语言:javascript
复制
  11:                        CONVERT 
代码语言:javascript
复制
  12:        (VARCHAR(MAX), MIN(CASE WHEN --event_name = 'sql_batch_completed'
代码语言:javascript
复制
  13:                                d_name = 'client_app_name'
代码语言:javascript
复制
  14:                               THEN d_value
代码语言:javascript
复制
  15:                     END)) AS [Client_app_name] ,
代码语言:javascript
复制
  16:                        CONVERT 
代码语言:javascript
复制
  17:        (VARCHAR(MAX), MIN(CASE WHEN  d_name = 'database_name'
代码语言:javascript
复制
  18:                                     AND d_package IS NOT NULL THEN d_value
代码语言:javascript
复制
  19:                           END)) AS [database_name] ,
代码语言:javascript
复制
  20:                           CONVERT
代码语言:javascript
复制
  21:                                   (VARCHAR(MAX), MIN(CASE WHEN  d_name = 'object_name'
代码语言:javascript
复制
  22:                                      THEN d_value
代码语言:javascript
复制
  23:                           END)) AS [object_name] ,
代码语言:javascript
复制
  24:                        CONVERT 
代码语言:javascript
复制
  25:        (BIGINT, MIN(CASE WHEN event_name = 'sql_batch_completed'
代码语言:javascript
复制
  26:                               AND d_name = 'duration'
代码语言:javascript
复制
  27:                               AND d_package IS NULL THEN d_value
代码语言:javascript
复制
  28:                     END)) AS [sql_statement_completed.duration] ,
代码语言:javascript
复制
  29:             
代码语言:javascript
复制
  30:                        CONVERT 
代码语言:javascript
复制
  31:        (VARCHAR(MAX), MIN(CASE WHEN d_name = 'sql_text'
代码语言:javascript
复制
  32:                                      THEN d_value
代码语言:javascript
复制
  33:                           END)) AS [sql_statement_completed.sql_text] ,
代码语言:javascript
复制
  34:                        CONVERT 
代码语言:javascript
复制
  35:        (VARCHAR(MAX), MIN(CASE WHEN d_name = 'username'
代码语言:javascript
复制
  36:                                     AND d_package IS NOT NULL THEN d_value
代码语言:javascript
复制
  37:                           END)) AS [username] 
代码语言:javascript
复制
  38:               FROM     ( SELECT    * ,
代码语言:javascript
复制
  39:                                    CONVERT(VARCHAR(400), NULL) AS attach_activity_id
代码语言:javascript
复制
  40:                          FROM      ( SELECT    event.value('(@name)[1]',
代码语言:javascript
复制
  41:                                                            'VARCHAR(400)') AS event_name ,
代码语言:javascript
复制
  42:                                                DENSE_RANK() OVER ( ORDER BY event ) AS unique_event_id ,
代码语言:javascript
复制
  43:                                                n.value('(@name)[1]',
代码语言:javascript
复制
  44:                                                        'VARCHAR(400)') AS d_name ,
代码语言:javascript
复制
  45:                                                n.value('(@package)[1]',
代码语言:javascript
复制
  46:                                                        'VARCHAR(400)') AS d_package ,
代码语言:javascript
复制
  47:                                                n.value('((value)[1]/text())[1]',
代码语言:javascript
复制
  48:                                                        'VARCHAR(MAX)') AS d_value ,
代码语言:javascript
复制
  49:                                                n.value('((text)[1]/text())[1]',
代码语言:javascript
复制
  50:                                                        'VARCHAR(MAX)') AS d_text
代码语言:javascript
复制
  51:                                      FROM      ( SELECT    ( SELECT
代码语言:javascript
复制
  52:                                                              CONVERT(XML, target_data)
代码语言:javascript
复制
  53:                                                              FROM
代码语言:javascript
复制
  54:                                                              sys.dm_xe_session_targets st
代码语言:javascript
复制
  55:                                                              JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
代码语言:javascript
复制
  56:                                                              WHERE
代码语言:javascript
复制
  57:                                                              s.name = 'DDL'
代码语言:javascript
复制
  58:                                                              AND st.target_name = 'ring_buffer'
代码语言:javascript
复制
  59:                                                            ) AS [x]
代码语言:javascript
复制
  60:                                                FOR
代码语言:javascript
复制
  61:                                                  XML PATH('') ,
代码语言:javascript
复制
  62:                                                      TYPE
代码语言:javascript
复制
  63:                                                ) AS the_xml ( x )
代码语言:javascript
复制
  64:                                                CROSS APPLY x.nodes('//event') e ( event )
代码语言:javascript
复制
  65:                                                CROSS APPLY event.nodes('*')
代码语言:javascript
复制
  66:                                                AS q ( n )
代码语言:javascript
复制
  67:                                    ) AS data_data
代码语言:javascript
复制
  68:                        ) AS activity_data
代码语言:javascript
复制
  69:               GROUP BY unique_event_id
代码语言:javascript
复制
  70:             )
代码语言:javascript
复制
  71:    SELECT  *
代码语言:javascript
复制
  72:    FROM    tt
代码语言:javascript
复制
  73:  

代码清单2.对扩展事件结果的优化读取方式

参考资料:http://blog.wharton.com.au/2011/06/13/part-5-openxml-and-xquery-optimisation-tips/

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/119752.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021年11月,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SQL Server中使用扩展事件捕捉所需的信息后,可以选择存放的位置。比如说内存或文件中,但无论存在哪里,其本质都是一个大XML。因此在SQL Server中读取该XML就是解析扩展事件结果的方式。
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档