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:XeventResutlDDLAudit*.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


