我如何尽快切碎此扩展事件XML?


13

我在SQL Server 2008 R2中创建了扩展事件会话。会话运行,并在事件发生时收集事件,完全符合您的期望。

如果在事件相对较少时切碎xml,则性能可以接受。当我有成千上万个事件时,将xml切碎是永远的。

我知道自己做错了事,只是对XML引擎的内部知识不足,无法理解。

这是我的扩展事件会话的定义:

IF EXISTS 
(
    SELECT 1 
    FROM sys.server_event_sessions dxs 
    WHERE dxs.name = 'queries'
)
BEGIN
    IF EXISTS (
        SELECT 1 
        FROM sys.dm_xe_sessions dxs 
        WHERE dxs.name = 'queries'
    )
    BEGIN
        ALTER EVENT SESSION queries ON SERVER STATE = STOP;
    END
    DROP EVENT SESSION queries ON SERVER;
END

CREATE EVENT SESSION queries ON SERVER 
ADD EVENT sqlserver.sql_statement_starting
(
    ACTION 
    (
        package0.collect_system_time
        --, package0.event_sequence
        , sqlserver.client_app_name
        , sqlserver.client_hostname
        --, sqlserver.database_name
        , sqlserver.plan_handle
        , sqlserver.sql_text
        , sqlserver.username
    )
    WHERE sqlserver.username = N'<some username>'
        AND sqlserver.database_id = 6 /* specific database */
        AND sqlserver.client_hostname <> '<my machine>'
) 
, ADD EVENT sqlserver.error_reported 
(
    ACTION 
    (
        package0.collect_system_time
        , sqlserver.client_app_name
        , sqlserver.client_hostname
        , sqlserver.plan_handle
        , sqlserver.sql_text
        , sqlserver.username
    )
    WHERE sqlserver.username <> N'<some username>'
        /* fluff errors below */
        AND error <> 5703 /* Changed language setting to %.*ls. */
        AND error <> 5701 /* Changed database context to '%.*ls'. */
        AND error <> 2528 /* DBCC execution completed. If DBCC printed error messages, contact your system administrator. */
        AND error <> 7969 /* No active open transactions. */
        --AND error <> 14205/* (unknown) */
        AND error <> 4035 /* Processed %I64d pages for database '%ls', file '%ls' on file %d. */
        AND error <> 18265/* Log was backed up. Database: %s, creation date(time): %s(%s), first LSN: %s, last LSN: %s, number of dump devices: %d, device information: (%s). This is an informational message only. No user action is required. */
        AND error <> 3014 /* %hs successfully processed %I64d pages in %d.%03d seconds (%d.%03d MB/sec). */
        AND error <> 14570/* (Job outcome) */
        AND error <> 8153 /* Warning: Null value is eliminated by an aggregate or other SET operation. */

)
ADD TARGET package0.ring_buffer
(
    SET max_memory = 102400
)
WITH 
(
    STARTUP_STATE=OFF
    , TRACK_CAUSALITY = ON
);
GO

IF EXISTS 
(
    SELECT 1 
    FROM sys.server_event_sessions dxs 
    WHERE dxs.name = 'queries'
)
BEGIN
    ALTER EVENT SESSION queries ON SERVER STATE = START;
END

这就是我粉碎结果的方式:

/***************************

shred the Event Data into readable form

***************************/

DECLARE @xml XML;

SELECT TOP(1) @xml = CONVERT(xml, xet.target_data)
FROM sys.dm_xe_session_targets AS xet
    INNER JOIN sys.dm_xe_sessions AS xe ON (xe.address = xet.event_session_address)
WHERE xe.name = 'queries';

SELECT t.EventName
    , DateStamp = DATEADD(HOUR, -6, t.EventDateStamp)
    , DatabaseName = d.name
    , t.ErrorNumber
    , t.ErrorSeverity
    , t.ErrorState
    , t.ErrorMessage
    , t.CollectSystemTime
    , t.ClientAppName
    , t.ClientHostName
    , t.PlanHandle
    , t.SqlText
    , t.UserName
FROM (
        SELECT EventName = s.value('(@name)[1]','varchar(500)')
            , EventDateStamp = s.value('(@timestamp)[1]','datetime')
            , DatabaseID = s.value('(data[(@name)[1] eq "source_database_id"]/value/text())[1]','varchar(255)')
            , ErrorNumber = s.value('(data[(@name)[1] eq "error"]/value/text())[1]','int')
            , ErrorSeverity = s.value('(data[(@name)[1] eq "severity"]/value/text())[1]','int')
            , ErrorState = s.value('(data[(@name)[1] eq "state"]/value/text())[1]','int')
            , ErrorMessage = s.value('(data[(@name)[1] eq "message"]/value/text())[1]','varchar(255)')
            , CollectSystemTime = s.value('(action[(@name)[1] eq "collect_system_time"]/text/text())[1]','varchar(255)')
            , ClientAppName = s.value('(action[(@name)[1] eq "client_app_name"]/value/text())[1]','varchar(255)')
            , ClientHostName = s.value('(action[(@name)[1] eq "client_hostname"]/value/text())[1]','varchar(255)')
            , PlanHandle = CONVERT(xml, s.value('(action[(@name)[1] eq "plan_handle"]/value/text())[1]','varchar(255)')).value('(plan/@handle)[1]', 'varchar(255)')
            , SqlText = s.value('(action[(@name)[1] eq "sql_text"]/value/text())[1]','nvarchar(max)')
            , UserName = s.value('(action[(@name)[1] eq "username"]/value/text())[1]','varchar(128)')
        FROM @xml.nodes('/RingBufferTarget/event') AS xm(s)
    ) t
    LEFT JOIN sys.databases d ON t.DatabaseID = d.database_id
ORDER BY t.UserName
    , t.EventDateStamp;

2
您是否已查看过此内容(即使它是最新版本的)?
汤姆五世-试试topanswers.xyz 2015年

1
我知道这不会帮到您,但是我认为XML粉碎是使用昂贵的核心许可证的最糟糕的方法。是否可以使用PowerShell从外部进行粉碎?
spaghettidba


1
很快,IBM的DB2.DB将XML作为BLOB(文本),分解为关系表或作为完全优化的本机XML数据模型直接支持。(有人告诉我,当他们最后添加PureXML支持时,他们非常接近最终将名称更改为DB3;这被认为是一项重大进步。)—声明者:我对PureXML的设计产生了一些影响,尽管我当时并未从事该项目,但我仍在IBM工作。
keshlam

1
@MaxVernon-关于,OPTION (Optimize FOR (@xml = Null))您也可以使用OPTION (QUERYTRACEON 4130 stackoverflow.com/a/3979266/73226
Martin Smith,

Answers:


11

感谢@Tom V标识了此博客文章,该文章确定了对临时表的需求。

适应博客文章中的想法,现在可以非常快速地工作:

/***************************

shred the Event Data into readable form

***************************/

DECLARE @xml XML;

SELECT TOP(1) @xml = CONVERT(xml, xet.target_data)
FROM sys.dm_xe_session_targets AS xet
    INNER JOIN sys.dm_xe_sessions AS xe ON (xe.address = xet.event_session_address)
WHERE xe.name = 'queries';

IF OBJECT_ID('tempdb..#xmlResults') IS NOT NULL
DROP TABLE #xmlResults;

CREATE TABLE #xmlResults
(
    RowNum INT NOT NULL
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , xeXML XML NOT NULL
);

INSERT INTO #xmlResults (xeXML)
SELECT xm.s.query('.')
FROM @xml.nodes('/RingBufferTarget/event') AS xm(s)
OPTION (Optimize FOR (@xml = Null)); -- Useful for SQL 2008

SELECT *
FROM #xmlResults

SELECT t.EventName
    , DateStamp = DATEADD(HOUR, -6, t.EventDateStamp)
    , DatabaseName = d.name
    , t.ErrorNumber
    , t.ErrorSeverity
    , t.ErrorState
    , t.ErrorMessage
    , t.CollectSystemTime
    , t.ClientAppName
    , t.ClientHostName
    , t.PlanHandle
    , t.SqlText
    , t.UserName
FROM (
        SELECT EventName =          xeXML.value('(event/@name)[1]','varchar(500)')
            , EventDateStamp =      xeXML.value('(event/@timestamp)[1]','datetime')
            , DatabaseID =          xeXML.value('(event/data[(@name)[1] eq "source_database_id"]/value/text())[1]','varchar(255)')
            , ErrorNumber =         xeXML.value('(event/data[(@name)[1] eq "error"]/value/text())[1]','varchar(255)')
            , ErrorSeverity =       xeXML.value('(event/data[(@name)[1] eq "severity"]/value/text())[1]','varchar(255)')
            , ErrorState =          xeXML.value('(event/data[(@name)[1] eq "state"]/value/text())[1]','varchar(255)')
            , ErrorMessage =        xeXML.value('(event/data[(@name)[1] eq "message"]/value/text())[1]','varchar(255)')
            , CollectSystemTime =   xeXML.value('(event/action[(@name)[1] eq "collect_system_time"]/text/text())[1]','varchar(255)')
            , ClientAppName =       xeXML.value('(event/action[(@name)[1] eq "client_app_name"]/value/text())[1]','varchar(255)')
            , ClientHostName =      xeXML.value('(event/action[(@name)[1] eq "client_hostname"]/value/text())[1]','varchar(255)')
            , PlanHandle = CONVERT(xml, xeXML.value('(event/action[(@name)[1] eq "plan_handle"]/value/text())[1]','varchar(255)')).value('(plan/@handle)[1]', 'varchar(255)')
            , SqlText =             xeXML.value('(event/action[(@name)[1] eq "sql_text"]/value/text())[1]','nvarchar(max)')
            , UserName =            xeXML.value('(event/action[(@name)[1] eq "username"]/value/text())[1]','varchar(128)')
        FROM #xmlResults xm
    ) t
    LEFT JOIN sys.databases d ON t.DatabaseID = d.database_id
ORDER BY t.UserName
    , t.EventDateStamp;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.