zoukankan      html  css  js  c++  java
  • SQL Server定时自动抓取耗时SQL并归档数据发邮件脚本分享

    SQL Server定时自动抓取耗时SQL并归档数据发邮件脚本分享

    第一步建库和建表

    USE [master]
    GO
    
    CREATE DATABASE [MonitorElapsedHighSQL]
    GO
    --建表
    
    USE [MonitorElapsedHighSQL]
    GO
    
    
     --1、表[SQLCountStatisticsByDay]
      --抓取到的sql语句数量
    CREATE TABLE [dbo].[SQLCountStatisticsByDay]
        (
          id INT IDENTITY(1, 1)  PRIMARY KEY ,
          [SQLCount] INT ,
          [gettime] DATETIME
        )
    
    CREATE INDEX [Idx_SQLCountStatisticsByDay_SQLCount] ON [MonitorElapsedHighSQL].[dbo].[SQLCountStatisticsByDay]([SQLCount])
    CREATE INDEX [Idx_SQLCountStatisticsByDay_gettime] ON [MonitorElapsedHighSQL].[dbo].[SQLCountStatisticsByDay]([gettime])
    GO
    
    
    
     --2、表[MostElapsedStatisticsByDay]
     --每条不同的sql耗时最多
    CREATE TABLE [dbo].[MostElapsedStatisticsByDay]
        (
          id INT IDENTITY(1, 1)
                 PRIMARY KEY ,
          [ElapsedMS] INT ,
          [IOReads] BIGINT ,
          [IOWrites] BIGINT ,
          [DBName] NVARCHAR(128) ,
          [paramlist] NVARCHAR(MAX) ,
          [planstmttext] NVARCHAR(MAX) ,
          [stmttext] NVARCHAR(MAX) ,
          [xmlplan] XML ,
          [gettime] DATETIME
        )
    
    CREATE INDEX [Idx_MostElapsedStatisticsByDay_ElapsedMS] ON [MonitorElapsedHighSQL].[dbo].[MostElapsedStatisticsByDay]([ElapsedMS])
    CREATE INDEX [Idx_MostElapsedStatisticsByDay_gettime] ON [MonitorElapsedHighSQL].[dbo].[MostElapsedStatisticsByDay]([gettime])
    GO
    
    
     --3、表[MostIOReadStatisticsByDay]
    --每条不同的sql的IOread最多
    CREATE TABLE [dbo].[MostIOReadStatisticsByDay]
        (
          id INT IDENTITY(1, 1)
                 PRIMARY KEY ,
          [IOReads] BIGINT ,
          [DBName] NVARCHAR(128) ,
          [paramlist] NVARCHAR(MAX) ,
          [planstmttext] NVARCHAR(MAX) ,
          [stmttext] NVARCHAR(MAX) ,
          [xmlplan] XML ,
          [gettime] DATETIME
        )
    
    CREATE INDEX [Idx_MostIOReadStatisticsByDay_IOReads] ON [MonitorElapsedHighSQL].[dbo].[MostIOReadStatisticsByDay]([IOReads])
    CREATE INDEX [Idx_MostIOReadStatisticsByDay_gettime] ON [MonitorElapsedHighSQL].[dbo].[MostIOReadStatisticsByDay]([gettime])
    GO
    
    
     --4、表[MostIOWriteStatisticsByDay]
    --每条不同的sql的IOwrite最多
    CREATE TABLE [dbo].[MostIOWriteStatisticsByDay]
        (
          id INT IDENTITY(1, 1)
                 PRIMARY KEY ,
          [IOWrites] BIGINT ,
          [DBName] NVARCHAR(128) ,
          [paramlist] NVARCHAR(MAX) ,
          [planstmttext] NVARCHAR(MAX) ,
          [stmttext] NVARCHAR(MAX) ,
          [xmlplan] XML ,
          [gettime] DATETIME
        )
    
    CREATE INDEX [Idx_MostIOWriteStatisticsByDay_IOWrites] ON [MonitorElapsedHighSQL].[dbo].[MostIOWriteStatisticsByDay]([IOWrites])
    CREATE INDEX [Idx_MostIOWriteStatisticsByDay_gettime] ON [MonitorElapsedHighSQL].[dbo].[MostIOWriteStatisticsByDay]([gettime])
    GO
    
    
     --5、表[sp_executesqlCountStatisticsByDay]
    --使用sp_executesql的sql有多少条
    CREATE TABLE [dbo].[sp_executesqlCountStatisticsByDay]
        (
          id INT IDENTITY(1, 1)
                 PRIMARY KEY ,
          [sp_executesqlCount] INT ,
          [DBName] NVARCHAR(128) ,
          [planstmttext] NVARCHAR(MAX) ,
          [gettime] DATETIME
        )
    
    CREATE INDEX [Idx_sp_executesqlCountStatisticsByDay_sp_executesqlCount] ON [MonitorElapsedHighSQL].[dbo].[sp_executesqlCountStatisticsByDay]([sp_executesqlCount])
    CREATE INDEX [Idx_sp_executesqlCountStatisticsByDay_gettime] ON [MonitorElapsedHighSQL].[dbo].[sp_executesqlCountStatisticsByDay]([gettime])
    GO

    第二步创建sp_who3存储过程

    -- http://sqlserverplanet.com/dba/a-better-sp_who2-using-dmvs-sp_who3
    
    USE [MonitorElapsedHighSQL]
    GO
    
    CREATE PROCEDURE [dbo].[sp_who3] 
    
    AS
    BEGIN
    
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    
    SELECT
        SPID                = er.session_id
        ,BlkBy              = CASE WHEN lead_blocker = 1 THEN -1 ELSE er.blocking_session_id END
        ,ElapsedMS          = er.total_elapsed_time
        ,CPU                = er.cpu_time
        ,IOReads            = er.logical_reads + er.reads
        ,IOWrites           = er.writes     
        ,Executions         = ec.execution_count  
        ,CommandType        = er.command         
        ,LastWaitType       = er.last_wait_type    
        ,ObjectName         = OBJECT_SCHEMA_NAME(qt.objectid,dbid) + '.' + OBJECT_NAME(qt.objectid, qt.dbid)  
        ,SQLStatement       =
            SUBSTRING
            (
                qt.text,
                er.statement_start_offset/2,
                (CASE WHEN er.statement_end_offset = -1
                    THEN LEN(CONVERT(nvarchar(MAX), qt.text)) * 2
                    ELSE er.statement_end_offset
                    END - er.statement_start_offset)/2
            )        
        ,STATUS             = ses.STATUS
        ,[Login]            = ses.login_name
        ,Host               = ses.host_name
        ,DBName             = DB_Name(er.database_id)
        ,StartTime          = er.start_time
        ,Protocol           = con.net_transport
        ,transaction_isolation =
            CASE ses.transaction_isolation_level
                WHEN 0 THEN 'Unspecified'
                WHEN 1 THEN 'Read Uncommitted'
                WHEN 2 THEN 'Read Committed'
                WHEN 3 THEN 'Repeatable'
                WHEN 4 THEN 'Serializable'
                WHEN 5 THEN 'Snapshot'
            END
        ,ConnectionWrites   = con.num_writes
        ,ConnectionReads    = con.num_reads
        ,ClientAddress      = con.client_net_address
        ,Authentication     = con.auth_scheme
        ,DatetimeSnapshot   = GETDATE()
        ,plan_handle        = er.plan_handle
    FROM sys.dm_exec_requests er
    LEFT JOIN sys.dm_exec_sessions ses
    ON ses.session_id = er.session_id
    LEFT JOIN sys.dm_exec_connections con
    ON con.session_id = ses.session_id
    OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) AS qt
    OUTER APPLY 
    (
        SELECT execution_count = MAX(cp.usecounts)
        FROM sys.dm_exec_cached_plans cp
        WHERE cp.plan_handle = er.plan_handle
    ) ec
    OUTER APPLY
    (
        SELECT
            lead_blocker = 1
        FROM master.dbo.sysprocesses sp
        WHERE sp.spid IN (SELECT blocked FROM master.dbo.sysprocesses)
        AND sp.blocked = 0
        AND sp.spid = er.session_id
    ) lb
    WHERE er.sql_handle IS NOT NULL
    AND er.session_id != @@SPID
    ORDER BY
        CASE WHEN lead_blocker = 1 THEN -1 * 1000 ELSE -er.blocking_session_id END,
        er.blocking_session_id DESC,
        er.logical_reads + er.reads DESC,
        er.session_id
    
    END
    View Code

    第三步创建[usp_checkElapsedHighSQL]存储过程

    USE [MonitorElapsedHighSQL]
    GO
    /****** Object:  StoredProcedure [dbo].[usp_checkElapsedHighSQL]    Script Date: 2015/6/23 17:16:56 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    --创建存储过程
    CREATE  PROCEDURE [dbo].[usp_checkElapsedHighSQL] ( @SessionID INT )
    AS
        BEGIN
    
            IF  ( SELECT  OBJECT_ID('MonitorElapsedHighSQL.dbo.ElapsedHigh') ) IS NULL
                BEGIN
                     CREATE TABLE [MonitorElapsedHighSQL].[dbo].[ElapsedHigh]
                        (
                          id INT IDENTITY(1, 1)   PRIMARY KEY ,
                          [SPID] SMALLINT ,
                          [ElapsedMS] INT ,
                          [IOReads] BIGINT ,
                          [IOWrites] BIGINT ,
                          [DBName] NVARCHAR(128) ,
                          [plan_handle] VARBINARY(64) ,
                          [paramlist] NVARCHAR(MAX) ,
                          [planstmttext] NVARCHAR(MAX) ,
                          [stmttext] NVARCHAR(MAX) ,
                          [xmlplan] XML,
                          [gettime] DATETIME
                        )
    
                    CREATE INDEX [Idx_ElapsedHigh_ElapsedMS] ON [MonitorElapsedHighSQL].[dbo].[ElapsedHigh]([ElapsedMS])
                    CREATE INDEX [Idx_ElapsedHigh_IOReads] ON [MonitorElapsedHighSQL].[dbo].[ElapsedHigh]([IOReads])
                     
                END
    
            IF  ( SELECT  OBJECT_ID('MonitorElapsedHighSQL.dbo.ElapsedHigh') ) IS NOT NULL
                BEGIN
            
                    SET NOCOUNT ON 
    
                    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    
                    DECLARE @Duration INT -- in milliseconds, 10000 = 10 sec
                    DECLARE @now DATETIME
                    DECLARE @plan_handle VARBINARY(64)
                    DECLARE @ElapsedMS INT
                    DECLARE @SPID INT
                    DECLARE @IOReads BIGINT
                    DECLARE @IOWrites BIGINT
                    DECLARE @DBName NVARCHAR(128)
                    DECLARE @planstmttext NVARCHAR(MAX)
                    DECLARE @stmttext NVARCHAR(MAX)
                    DECLARE @paramlist NVARCHAR(MAX)
                    DECLARE @plan_xml XML
                    DECLARE @paramtb TABLE
                        (
                          paramlist NVARCHAR(MAX) ,
                          planstmttext NVARCHAR(MAX)
                        )
                    DECLARE @paramtb2 TABLE
                        (
                          paramlist NVARCHAR(MAX) ,
                          planstmttext NVARCHAR(MAX)
                        )
    
                    SELECT  @Duration = 10000  --★Do -- in milliseconds, 10000 = 10 sec
    
    
    
                    IF OBJECT_ID('tempdb..#ElapsedHigh') IS NOT NULL
                        BEGIN
                            DROP TABLE [#ElapsedHigh]  --删除临时表  
                        END 
    
    
    --建临时表
                    CREATE TABLE [#ElapsedHigh]
                        (
                          [SPID] SMALLINT ,
                          [BlkBy] INT ,
                          [ElapsedMS] INT ,
                          [CPU] INT ,
                          [IOReads] BIGINT ,
                          [IOWrites] BIGINT ,
                          [Executions] INT ,
                          [CommandType] NVARCHAR(40) ,
                          [LastWaitType] NVARCHAR(60) ,
                          [ObjectName] NVARCHAR(1000) ,
                          [SQLStatement] NVARCHAR(MAX) ,
                          [STATUS] NVARCHAR(30) ,
                          [Login] NVARCHAR(128) ,
                          [Host] NVARCHAR(128) ,
                          [DBName] NVARCHAR(128) ,
                          [StartTime] DATETIME ,
                          [Protocol] NVARCHAR(40) ,
                          [transaction_isolation] NVARCHAR(100) ,
                          [ConnectionWrites] INT ,
                          [ConnectionReads] INT ,
                          [ClientAddress] VARCHAR(48) ,
                          [AUTHENTICATION] NVARCHAR(40) ,
                          [DatetimeSnapshot] DATETIME ,
                          [plan_handle] VARBINARY(64)
                        )
    
    
    
    
    --处理逻辑
                    INSERT  INTO [#ElapsedHigh]
                            ( [SPID] ,
                              [BlkBy] ,
                              [ElapsedMS] ,
                              [CPU] ,
                              [IOReads] ,
                              [IOWrites] ,
                              [Executions] ,
                              [CommandType] ,
                              [LastWaitType] ,
                              [ObjectName] ,
                              [SQLStatement] ,
                              [STATUS] ,
                              [Login] ,
                              [Host] ,
                              [DBName] ,
                              [StartTime] ,
                              [Protocol] ,
                              [transaction_isolation] ,
                              [ConnectionWrites] ,
                              [ConnectionReads] ,
                              [ClientAddress] ,
                              [AUTHENTICATION] ,
                              [DatetimeSnapshot] ,
                              [plan_handle]
                            )
                            EXEC [MonitorElapsedHighSQL].[dbo].[sp_who3]
    
            --如果传入的是会话ID 只显示所在会话ID的信息
                    IF ( @SessionID IS NOT NULL AND @SessionID <> 0 )
                        BEGIN 
    
                            SELECT TOP 1
                                    @ElapsedMS = [ElapsedMS] ,
                                    @SPID = [SPID] ,
                                    @plan_handle = [plan_handle] ,
                                    @IOReads = [IOReads] ,
                                    @IOWrites = [IOWrites] ,
                                    @DBName = [DBName]
                            FROM    [#ElapsedHigh]
                            WHERE   [#ElapsedHigh].[SPID] = @SessionID
    
    
                            SELECT  @stmttext = [text]  FROM    sys.fn_get_sql(@plan_handle)
    
    
    
                            BEGIN TRY
            -- convert may fail due to exceeding 128 depth limit
                                SELECT  @plan_xml = CONVERT(XML, query_plan)
                                FROM    sys.dm_exec_text_query_plan(@plan_handle, 0, -1)
                            END TRY
                            BEGIN CATCH 
                                SELECT  @plan_xml = NULL
                            END CATCH;
    
                            WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS sp)
    INSERT @paramtb ( [paramlist], [planstmttext] )
        SELECT 
            parameter_list.param_node.value('(./@Column)[1]', 'nvarchar(128)') +'='+ parameter_list.param_node.value('(./@ParameterCompiledValue)[1]', 'nvarchar(max)')  AS paramlist,
            ISNULL(@plan_xml.value('(//@StatementText)[1]', 'nvarchar(max)'), N'Unknown Statement') AS stmttext
        FROM (SELECT @plan_xml AS xml_showplan) AS t
            OUTER APPLY t.xml_showplan.nodes('//sp:ParameterList/sp:ColumnReference') AS parameter_list (param_node)
            
                            SELECT TOP 1
                                    @SPID spid ,
                                    @ElapsedMS ElapsedMS ,
                                    @IOReads IOReads ,
                                    @IOWrites IOReads ,
                                    @DBName DBName ,
                                    @plan_handle plan_handle ,
                                    @plan_xml planxml,
                                    @stmttext stmttext ,
                                    [planstmttext] planstmttext ,
                                    ( SELECT    [paramlist] + '  '
                                      FROM      @paramtb
                                      WHERE     [planstmttext] = A.[planstmttext]
                                    FOR
                                      XML PATH('')
                                    ) AS [paramlist]
                            FROM    @paramtb A
                            GROUP BY [planstmttext]
    
                        END
                    ELSE
            --如果没有对存储过程传入参数,那么显示耗时最多的那条SQL的信息
                        BEGIN 
    
                            SELECT TOP 1
                                    @ElapsedMS = [ElapsedMS] ,
                                    @SPID = [SPID] ,
                                    @plan_handle = [plan_handle] ,
                                    @IOReads = [IOReads] ,
                                    @IOWrites = [IOWrites] ,
                                    @DBName = [DBName]
                            FROM    [#ElapsedHigh] WHERE [#ElapsedHigh].[DBName] NOT IN('master','distribution','model','msdb','tempdb')
                            ORDER BY [ElapsedMS] DESC 
    
                            SELECT  @stmttext = [text]  FROM    sys.fn_get_sql(@plan_handle)
    
    
    
    --抓取占用时间长的SQL
                            IF ( @ElapsedMS > @Duration )
                                BEGIN 
                                    SELECT  @now = GETDATE()
    
    
                                    BEGIN TRY
            -- convert may fail due to exceeding 128 depth limit
                                        SELECT  @plan_xml = CONVERT(XML, query_plan)
                                        FROM    sys.dm_exec_text_query_plan(@plan_handle,
                                                                  0, -1)
                                    END TRY
                                    BEGIN CATCH
                                        SELECT  @plan_xml = NULL
                                    END CATCH;
    
                                    WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS sp)
    INSERT @paramtb ( [paramlist], [planstmttext] )
        SELECT 
            parameter_list.param_node.value('(./@Column)[1]', 'nvarchar(128)') +'='+ parameter_list.param_node.value('(./@ParameterCompiledValue)[1]', 'nvarchar(max)')  AS paramlist,
            ISNULL(@plan_xml.value('(//@StatementText)[1]', 'nvarchar(max)'), N'Unknown Statement') AS stmttext
        FROM (SELECT @plan_xml AS xml_showplan) AS t
            OUTER APPLY t.xml_showplan.nodes('//sp:ParameterList/sp:ColumnReference') AS parameter_list (param_node)
            
    
                                    INSERT  @paramtb2( [planstmttext] , [paramlist])
                                            SELECT TOP 1
                                                    [planstmttext] ,
                                                    ( SELECT    [paramlist] + '  '
                                                      FROM      @paramtb
                                                      WHERE     [planstmttext] = A.[planstmttext]
                                                    FOR
                                                      XML PATH('')
                                                    ) AS [paramlist]
                                            FROM    @paramtb A
                                            GROUP BY [planstmttext]
    
    
                                    SELECT TOP 1
                                            @planstmttext = [planstmttext] ,
                                            @paramlist = [paramlist]
                                    FROM    @paramtb2
    
                                    INSERT  INTO [MonitorElapsedHighSQL].[dbo].[ElapsedHigh]
                                            ( [SPID] ,
                                              [ElapsedMS] ,
                                              [IOReads] ,
                                              [IOWrites] ,
                                              [DBName] ,
                                              [plan_handle] ,
                                              [paramlist] ,
                                              [stmttext] ,
                                              [planstmttext] ,
                                              [xmlplan],
                                              [gettime]
                                            )
                                    VALUES  ( @SPID , -- SPID - smallint
                                              @ElapsedMS , -- ElapsedMS - int
                                              @IOReads , -- IOReads - bigint
                                              @IOWrites , -- IOWrites - bigint
                                              @DBName , -- DBName - nvarchar(128)
                                              @plan_handle , -- plan_handle - varbinary(64)
                                              @paramlist , -- paramlist - nvarchar(max)
                                              @stmttext , -- stmttext - nvarchar(max)
                                              @planstmttext , -- planstmttext - nvarchar(max)
                                              @plan_xml ,  --plan_xml - xml
                                              @now  -- gettime - datetime
                                            )
    
                                END 
                        END
    
                END
    
        END
    View Code

    第四步创建[usp_Resettbname]存储过程 

    USE [MonitorElapsedHighSQL]
    GO
    --重设ElapsedHigh表名,进行归档
    CREATE  PROCEDURE [dbo].[usp_Resettbname]
    AS
        BEGIN
           
             IF EXISTS ( SELECT  OBJECT_ID('MonitorElapsedHighSQL.dbo.ElapsedHigh') )
                BEGIN
                   --kill掉数据库所有连接
                    DECLARE @DBNAME NVARCHAR(100)
                    DECLARE @SQL NVARCHAR(MAX)
                    DECLARE @SPID NVARCHAR(100)
                    DECLARE @OwnSPID NVARCHAR(100)
                    DECLARE @TBNAME NVARCHAR(1000)
    
                    SELECT  @OwnSPID = @@SPID
                    SET @DBNAME = 'MonitorElapsedHighSQL'  
    
    
                    DECLARE CurDBName CURSOR
                    FOR
                        SELECT  [spid]
                        FROM    sys.sysprocesses
                        WHERE   [spid] >= 50
                                AND DBID = DB_ID(@DBNAME)
    
                    OPEN CurDBName
                    FETCH NEXT FROM CurDBName INTO @SPID
    
                    WHILE @@FETCH_STATUS = 0
                        BEGIN  
            --kill process 不kill掉本存储过程的spid
                            IF ( @SPID <> @OwnSPID )
                                BEGIN
                                    SET @SQL = N'kill ' + @SPID
                                    EXEC (@SQL)
                                END 
    
                            FETCH NEXT FROM CurDBName INTO @SPID
                        END
                    CLOSE CurDBName
                    DEALLOCATE CurDBName
    
                    SET @TBNAME='ElapsedHigh'+CONVERT(NVARCHAR(200), GETDATE(), 112) 
    
                    EXEC sys.[sp_rename] @objname = N'ElapsedHigh', -- nvarchar(1035)
                        @newname =@TBNAME    -- sysname
    
                    
    
                END
     
    
        END
    View Code

    第五步创建[usp_StatisticsTask]存储过程

    USE [MonitorElapsedHighSQL]
    GO
    /****** Object:  StoredProcedure [dbo].[usp_StatisticsTask]    Script Date: 2015/6/24 18:05:38 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    
    --创建存储过程
    CREATE   PROCEDURE [dbo].[usp_StatisticsTask]
    AS
        BEGIN
    
            IF ( ( SELECT   OBJECT_ID('MonitorElapsedHighSQL.dbo.SQLCountStatisticsByDay')
                 ) IS NULL
                 AND ( SELECT   OBJECT_ID('MonitorElapsedHighSQL.dbo.MostElapsedStatisticsByDay')
                     ) IS NULL
                 AND ( SELECT   OBJECT_ID('MonitorElapsedHighSQL.dbo.MostIOReadStatisticsByDay')
                     ) IS NULL
                 AND ( SELECT   OBJECT_ID('MonitorElapsedHighSQL.dbo.MostIOWriteStatisticsByDay')
                     ) IS NULL
                 AND ( SELECT   OBJECT_ID('MonitorElapsedHighSQL.dbo.sp_executesqlCountStatisticsByDay')
                     ) IS NULL
               )
                BEGIN
                    RETURN 1
                     
                END
            ELSE
                BEGIN
                    --最耗时SQL
                    INSERT  INTO [dbo].[MostElapsedStatisticsByDay]
                            ( [ElapsedMS] ,
                              [IOReads] ,
                              [IOWrites] ,
                              [DBName] ,
                              [paramlist] ,
                              [planstmttext] ,
                              [stmttext] ,
                              [xmlplan] ,
                              [gettime]
                            )
                            SELECT  [ElapsedMS] ,
                                    [IOReads] ,
                                    [IOWrites] ,
                                    [DBName] ,
                                    [paramlist] ,
                                    [planstmttext] ,
                                    [stmttext] ,
                                    [xmlplan] ,
                                    GETDATE()
                            FROM    ( SELECT    ROW_NUMBER() OVER ( PARTITION BY spid ORDER BY [ElapsedMS] DESC ) rowid ,
                                                *
                                      FROM      [ElapsedHigh]
                                      WHERE     [DBName] NOT IN ( 'MASTER',
                                                                  'MODEL', 'MSDB',
                                                                  'ReportServer',
                                                                  'ReportServerTempDB',
                                                                  'distribution' )
                                    ) t
                            WHERE   rowid = 1
    
    
    
    --读IO最多SQL
                    INSERT  INTO [dbo].[MostIOReadStatisticsByDay]
                            ( [IOReads] ,
                              [DBName] ,
                              [paramlist] ,
                              [planstmttext] ,
                              [stmttext] ,
                              [xmlplan] ,
                              [gettime]
                            )
                            SELECT  [IOReads] ,
                                    [DBName] ,
                                    [paramlist] ,
                                    [planstmttext] ,
                                    [stmttext] ,
                                    [xmlplan] ,
                                    GETDATE()
                            FROM    ( SELECT    ROW_NUMBER() OVER ( PARTITION BY spid ORDER BY [IOReads] DESC ) rowid ,
                                                *
                                      FROM      [ElapsedHigh]
                                      WHERE     [DBName] NOT IN ( 'MASTER',
                                                                  'MODEL', 'MSDB',
                                                                  'ReportServer',
                                                                  'ReportServerTempDB',
                                                                  'distribution' )
                                    ) t
                            WHERE   rowid = 1
    
    
    
    --写IO最多SQL
                    INSERT  INTO [dbo].[MostIOWriteStatisticsByDay]
                            ( [IOWrites] ,
                              [DBName] ,
                              [paramlist] ,
                              [planstmttext] ,
                              [stmttext] ,
                              [xmlplan] ,
                              [gettime]
                            )
                            SELECT  [IOWrites] ,
                                    [DBName] ,
                                    [paramlist] ,
                                    [planstmttext] ,
                                    [stmttext] ,
                                    [xmlplan] ,
                                    GETDATE()
                            FROM    ( SELECT    ROW_NUMBER() OVER ( PARTITION BY spid ORDER BY [IOWrites] DESC ) rowid ,
                                                *
                                      FROM      [ElapsedHigh]
                                      WHERE     [DBName] NOT IN ( 'MASTER',
                                                                  'MODEL', 'MSDB',
                                                                  'ReportServer',
                                                                  'ReportServerTempDB',
                                                                  'distribution' )
                                    ) t
                            WHERE   rowid = 1
    
    
    
    --统计sp_executesql次数
                    DECLARE @tbsp_executesqlCountStatisticsByDay TABLE
                        (
                          [DBName] [nvarchar](128) ,
                          [planstmttext] [nvarchar](MAX)
                        )
                    DECLARE @sp_executesqlCount INT
    
                    INSERT  INTO @tbsp_executesqlCountStatisticsByDay
                            ( [DBName] ,
                              [planstmttext] 
                            )
                            SELECT  [DBName] ,
                                    [planstmttext]
                            FROM    ( SELECT    ROW_NUMBER() OVER ( PARTITION BY spid ORDER BY [IOWrites] DESC ) rowid ,
                                                *
                                      FROM      [ElapsedHigh]
                                      WHERE     [planstmttext] LIKE '(@%'
                                                AND [DBName] NOT IN ( 'MASTER',
                                                                  'MODEL', 'MSDB',
                                                                  'ReportServer',
                                                                  'ReportServerTempDB',
                                                                  'distribution' )
                                    ) t
                            WHERE   rowid = 1
    
                    SELECT  @sp_executesqlCount = COUNT(*)
                    FROM    @tbsp_executesqlCountStatisticsByDay
    
                    INSERT  INTO [dbo].[sp_executesqlCountStatisticsByDay]
                            ( [sp_executesqlCount] ,
                              [DBName] ,
                              [planstmttext] ,
                              [gettime]
                            )
                            SELECT  @sp_executesqlCount ,
                                    [DBName] ,
                                    [planstmttext] ,
                                    GETDATE()
                            FROM    @tbsp_executesqlCountStatisticsByDay
    
    
    
    --统计一共有多少SQL被抓取
                    INSERT  INTO [dbo].[SQLCountStatisticsByDay]
                            ( [SQLCount] ,
                              [gettime]
                            )
                            SELECT  COUNT(DISTINCT ( [planstmttext] )) ,
                                    GETDATE()
                            FROM    [dbo].[ElapsedHigh]
                            WHERE   [DBName] NOT IN ( 'MASTER', 'MODEL', 'MSDB',
                                                      'ReportServer',
                                                      'ReportServerTempDB',
                                                      'distribution' )
    
    
                END
    
    
       
        END
    View Code

    第六步创建[usp_SendStatisticsMail]存储过程

    USE [MonitorElapsedHighSQL]
    GO
    
    --对统计数据定时发邮件
    CREATE  PROCEDURE [dbo].[usp_SendStatisticsMail]
    AS
        BEGIN
           
            --定义变量
            DECLARE @SQL NVARCHAR(MAX)
            DECLARE @SQLConcat NVARCHAR(MAX)
            DECLARE @infoConcat NVARCHAR(MAX)
            DECLARE @finalSQL NVARCHAR(MAX)
    
    
            DECLARE @DBID NVARCHAR(MAX)
            DECLARE @servername NVARCHAR(200)
            DECLARE @date DATETIME
    
            DECLARE @sqlversion NVARCHAR(200)
            DECLARE @uptime NVARCHAR(200)
    
    
            --1.数据库版本信息
            SELECT  @sqlversion = @@version
    
    
            --2.数据库服务器已运行时间信息
            SELECT  @uptime = CONVERT(NVARCHAR(200), DATEDIFF(DAY, sqlserver_start_time, GETDATE()))
            FROM    sys.dm_os_sys_info WITH ( NOLOCK )
            OPTION  ( RECOMPILE )
    
    
    
            --3.查看数据库服务器名
            SELECT  @servername = LTRIM(@@servername)
    
    
            SET @date = GETDATE()
            SET @SQL = ' '
            SET @SQLConcat = ' '
            SET @infoConcat = ' '
    
    
    
            IF ( @servername IS NOT NULL AND @servername <> '' )
                BEGIN
                    SET @infoConcat = '<h3><font color="#FF0000">主机名:' + @ServerName + '</font></h3></br>'
                END
    
            IF ( @uptime IS NOT NULL  AND @uptime <> '' )
                BEGIN
                    SET @infoConcat = @infoConcat + '<h4>数据库服务器已运行天数:' + @uptime  + '天</h4></br>' 
                END
    
            IF ( @sqlversion IS NOT NULL AND @sqlversion <> '' )
                BEGIN
                    SET @infoConcat = @infoConcat + '<h4>数据库版本信息:' + @sqlversion + '</h4></br>'
                END
    
    
          -----------------------------------------------------------
    
    
            SET @SQL = N'<H3>[' + @servername + ']_前5条不同的最耗时SQL 表名:[MostElapsedStatisticsByDay] ------   邮件发出时间:' + CONVERT(NVARCHAR(200), @date, 120) + '</H3>'
                + '<table border="1">' + N'<tr>
    <th>[id]</th>
    <th>[耗时]</th>
    <th>[IO读次数]</th>
    <th>[IO写次数]</th>
    <th>[数据库名称]</th>
    <th>[执行计划SQL]</th>
    <th>[日期]</th>
    </tr>' + CAST(( SELECT TOP 5
                            [id] AS 'td' ,
                            '' ,
                            [ElapsedMS] AS 'td' ,
                            '' ,
                            [IOReads] AS 'td' ,
                            '' ,
                            [IOWrites] AS 'td' ,
                            '' ,
                            [DBName] AS 'td' ,
                            '' ,
                            LEFT([planstmttext], 100) AS 'td' ,
                            '' ,
                            CONVERT(DATE, [gettime]) AS 'td' ,
                            ''
                    FROM    [dbo].[MostElapsedStatisticsByDay]
                    WHERE   DATEPART(DAY, [gettime]) = DATEPART(DAY, GETDATE()) AND DATEPART(MONTH , [gettime]) = DATEPART(MONTH, GETDATE()) AND DATEPART(YEAR, [gettime]) = DATEPART(YEAR, GETDATE())
                    ORDER BY [ElapsedMS] DESC
                  FOR
                    XML PATH('tr') ,
                        ELEMENTS-- TYPE 
                  ) AS NVARCHAR(MAX)) + N'</table>';
            PRINT @SQL
    
            IF ( @SQL IS NOT NULL
                 AND @SQL <> ''
               )
                BEGIN
                    SET @SQLConcat = @SQL + @SQLConcat
    
                END
    
    
    
    
          --------------------------------------------------------
    
    
    
            SET @SQL = N'<H3>[' + @servername + ']_前5条I/O read最多的SQL 表名:[MostIOReadStatisticsByDay]------   邮件发出时间:' + CONVERT(NVARCHAR(200), @date, 120) + '</H3>'
                + '<table border="1">' + N'<tr>
    <th>[id]</th>
    <th>[IO读次数]</th>
    <th>[数据库名称]</th>
    <th>[执行计划SQL]</th>
    <th>[日期]</th>
    </tr>' + CAST(( SELECT TOP 5
                            [id] AS 'td' ,
                            '' ,
                            [IOReads] AS 'td' ,
                            '' ,
                            [DBName] AS 'td' ,
                            '' ,
                            LEFT([planstmttext], 100) AS 'td' ,
                            '' ,
                            CONVERT(DATE, [gettime]) AS 'td' ,
                            ''
                    FROM    [dbo].[MostIOReadStatisticsByDay]
                    WHERE   DATEPART(DAY, [gettime]) = DATEPART(DAY, GETDATE()) AND DATEPART(MONTH , [gettime]) = DATEPART(MONTH, GETDATE()) AND DATEPART(YEAR, [gettime]) = DATEPART(YEAR, GETDATE())
                    ORDER BY [IOReads] DESC
                  FOR
                    XML PATH('tr') ,
                        ELEMENTS-- TYPE 
                  ) AS NVARCHAR(MAX)) + N'</table>';
    
    
         
            IF ( @SQL IS NOT NULL
                 AND @SQL <> ''
               )
                BEGIN
                    SET @SQLConcat = @SQL + @SQLConcat
    
                END
    
    --      -----------------------------------------------------
    
    
    
            SET @SQL = N'<H3>[' + @servername + ']_前5条I/O write最多的SQL 表名:[MostIOWriteStatisticsByDay]------   邮件发出时间:'+ CONVERT(NVARCHAR(200), @date, 120) + '</H3>'
                + '<table border="1">' + N'<tr>
    <th>[id]</th>
    <th>[IO写次数]</th>
    <th>[数据库名称]</th>
    <th>[执行计划SQL]</th>
    <th>[日期]</th>
    </tr>' + CAST(( SELECT TOP 5
                            [id] AS 'td' ,
                            '' ,
                            [IOWrites] AS 'td' ,
                            '' ,
                            [DBName] AS 'td' ,
                            '' ,
                            LEFT([planstmttext], 100) AS 'td' ,
                            '' ,
                            CONVERT(DATE, [gettime]) AS 'td' ,
                            ''
                    FROM    [dbo].[MostIOWriteStatisticsByDay]
                    WHERE   DATEPART(DAY, [gettime]) = DATEPART(DAY, GETDATE()) AND DATEPART(MONTH , [gettime]) = DATEPART(MONTH, GETDATE()) AND DATEPART(YEAR, [gettime]) = DATEPART(YEAR, GETDATE())
                    ORDER BY [IOWrites] DESC
                  FOR
                    XML PATH('tr') ,
                        ELEMENTS-- TYPE 
                  ) AS NVARCHAR(MAX)) + N'</table>';
    
    
          
            IF ( @SQL IS NOT NULL
                 AND @SQL <> ''
               )
                BEGIN
                    SET @SQLConcat = @SQL + @SQLConcat
    
                END
    
    --      -------------------------------------------------------
    
    
    
    
            SET @SQL = N'<H3>[' + @servername + ']_前5条使用sp_executesql执行的SQL 表名:[sp_executesqlCountStatisticsByDay]------   邮件发出时间:'+ CONVERT(NVARCHAR(200), @date, 120) + '</H3>'
                + '<table border="1">' + N'<tr>
    <th>[id]</th>
    <th>[sp_executesql调用次数]</th>
    <th>[数据库名称]</th>
    <th>[执行计划SQL]</th>
    <th>[日期]</th>
    </tr>' + CAST(( SELECT TOP 5
                            [id] AS 'td' ,
                            '' ,
                            [sp_executesqlCount] AS 'td' ,
                            '' ,
                            [DBName] AS 'td' ,
                            '' ,
                            LEFT([planstmttext], 100) AS 'td' ,
                            '' ,
                            CONVERT(DATE, [gettime]) AS 'td' ,
                            ''
                    FROM    [dbo].[sp_executesqlCountStatisticsByDay]
                    WHERE   DATEPART(DAY, [gettime]) = DATEPART(DAY, GETDATE()) AND DATEPART(MONTH , [gettime]) = DATEPART(MONTH, GETDATE()) AND DATEPART(YEAR, [gettime]) = DATEPART(YEAR, GETDATE())
                    ORDER BY [sp_executesqlCount] DESC
                  FOR
                    XML PATH('tr') ,
                        ELEMENTS-- TYPE 
                  ) AS NVARCHAR(MAX)) + N'</table>';
    
         
            IF ( @SQL IS NOT NULL
                 AND @SQL <> ''
               )
                BEGIN
                    SET @SQLConcat = @SQL + @SQLConcat
    
                END
    
    --      --------------------------------------------------------
            
            SET @SQL = N'<H3>[' + @servername+ ']_SQL语句数量 表名:[SQLCountStatisticsByDay]------   邮件发出时间:' + CONVERT(NVARCHAR(200), @date, 120) + '</H3>'
                + '<table border="1">' + N'<tr>
    <th>[id]</th>
    <th>[SQL数量]</th>
    <th>[日期]</th>
    </tr>' + CAST(( SELECT  [id] AS 'td' ,
                            '' ,
                            [SQLCount] AS 'td' ,
                            '' ,
                            CONVERT(DATE, [gettime]) AS 'td' ,
                            ''
                    FROM    [dbo].[SQLCountStatisticsByDay]
                    WHERE   DATEPART(DAY, [gettime]) = DATEPART(DAY, GETDATE()) AND DATEPART(MONTH , [gettime]) = DATEPART(MONTH, GETDATE()) AND DATEPART(YEAR, [gettime]) = DATEPART(YEAR, GETDATE())
                  FOR
                    XML PATH('tr') ,
                        ELEMENTS-- TYPE 
                  ) AS NVARCHAR(MAX)) + N'</table>';
    
          
            IF ( @SQL IS NOT NULL
                 AND @SQL <> ''
               )
                BEGIN
                    SET @SQLConcat = @SQL + @SQLConcat
    
                END
    
          -----------------------------------------------
    
            IF ( @infoConcat IS NOT NULL AND @infoConcat <> '' AND @SQLConcat IS NOT NULL  AND @SQLConcat <> '')
                BEGIN
                    SET @finalSQL = @infoConcat + '</br></br>' + @SQLConcat
                    EXEC [msdb].[dbo].[sp_send_dbmail] @profile_name = 'SQLServer',
                        @recipients = 'dba@xx.com', -- varchar(max) --收件人
                        @subject = N'SQL Server 实例SQL语句抓取统计信息', -- nvarchar(255) 标题
                        @body_format = 'HTML', -- varchar(20) 正文格式可选值:text html
                        @body = @finalSQL
                END
    
    
         
    
    
        END
    View Code

    第七步创建AutocaptureElapsedHighSQL作业

    USE [msdb]
    GO
    /****** 对象:  Job [自动抓取耗时SQL]    脚本日期: 07/29/2014 15:44:57 ******/
    BEGIN TRANSACTION
    DECLARE @ReturnCode INT
    SELECT @ReturnCode = 0
    /****** 对象:  JobCategory [[Uncategorized (Local)]]]    脚本日期: 07/29/2014 15:44:57 ******/
    IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
    BEGIN
    EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    END
    
    DECLARE @jobId BINARY(16)
    EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'AutocaptureElapsedHighSQL', 
            @enabled=1, 
            @notify_level_eventlog=0, 
            @notify_level_email=0, 
            @notify_level_netsend=0, 
            @notify_level_page=0, 
            @delete_level=0, 
            @description=N'自动抓取耗时SQL', 
            @category_name=N'[Uncategorized (Local)]', 
            @owner_login_name=N'sa', @job_id = @jobId OUTPUT
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** 对象:  Step [execute usp_checkElapsedHighSQL script]    脚本日期: 07/29/2014 15:44:58 ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep  @job_name=N'AutocaptureElapsedHighSQL', @step_name=N'execute usp_checkElapsedHighSQL script', 
            @step_id=1, 
            @cmdexec_success_code=0, 
            @on_success_action=1, 
            @on_success_step_id=0, 
            @on_fail_action=2, 
            @on_fail_step_id=0, 
            @retry_attempts=0, 
            @retry_interval=0, 
            @os_run_priority=0, @subsystem=N'TSQL', 
            @command=N'exec [dbo].[usp_checkElapsedHighSQL] null',  --调用存储过程
            @database_name=N'MonitorElapsedHighSQL', 
            @flags=0
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_name=N'AutocaptureElapsedHighSQL', @name=N'ScheduleAutocaptureCheck', 
            @enabled=1, 
            @freq_type=4, 
            @freq_interval=1, 
            @freq_subday_type=4, 
            @freq_subday_interval=1, --每一分钟抓取一次耗时SQL
            @freq_relative_interval=0, 
            @freq_recurrence_factor=0, 
            @active_start_date=20110224, 
            @active_end_date=99991231, 
            @active_start_time=200, 
            @active_end_time=235959
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_name=N'AutocaptureElapsedHighSQL', @server_name = N'(local)'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    COMMIT TRANSACTION
    GOTO EndSave
    QuitWithRollback:
        IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
    EndSave:
    View Code

    第八步创建ResetcheckElapsedHighSQLtbname作业

    USE [msdb]
    GO
    /****** 对象:  Job [定时改表名]    脚本日期: 07/29/2014 15:44:57 ******/
    BEGIN TRANSACTION
    DECLARE @ReturnCode INT
    SELECT @ReturnCode = 0
    /****** 对象:  JobCategory [[Uncategorized (Local)]]]    脚本日期: 07/29/2014 15:44:57 ******/
    IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
    BEGIN
    EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    END
    
    DECLARE @jobId BINARY(16)
    EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'ResetcheckElapsedHighSQLtbname', 
            @enabled=1, 
            @notify_level_eventlog=0, 
            @notify_level_email=0, 
            @notify_level_netsend=0, 
            @notify_level_page=0, 
            @delete_level=0, 
            @description=N'修改抓取耗时SQL的表名', 
            @category_name=N'[Uncategorized (Local)]', 
            @owner_login_name=N'sa', @job_id = @jobId OUTPUT
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** 对象:  Step [execute usp_checkElapsedHighSQL script]    脚本日期: 07/29/2014 15:44:58 ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep  @job_name=N'ResetcheckElapsedHighSQLtbname', @step_name=N'execute usp_Resettbname script', 
            @step_id=1, 
            @cmdexec_success_code=0, 
            @on_success_action=1, 
            @on_success_step_id=0, 
            @on_fail_action=2, 
            @on_fail_step_id=0, 
            @retry_attempts=0, 
            @retry_interval=0, 
            @os_run_priority=0, @subsystem=N'TSQL', 
            @command=N'exec [dbo].[usp_Resettbname] ',  --调用存储过程
            @database_name=N'MonitorElapsedHighSQL', 
            @flags=0
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_name=N'ResetcheckElapsedHighSQLtbname', @name=N'Scheduleusp_Resettbname', 
        @enabled=1, 
            @freq_type=4, 
            @freq_interval=1, 
            @freq_subday_type=1, 
            @freq_subday_interval=1, 
            @freq_relative_interval=0, 
            @freq_recurrence_factor=0, 
            @active_start_date=20110224, 
            @active_end_date=99991231, 
            @active_start_time=235900, 
            @active_end_time=235959
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_name=N'ResetcheckElapsedHighSQLtbname', @server_name = N'(local)'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    COMMIT TRANSACTION
    GOTO EndSave
    QuitWithRollback:
        IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
    EndSave:
    View Code

    第九步创建StatisticsforElapsedHigh作业

    USE [msdb]
    GO
    /****** 对象:  Job [定时统计[ElapsedHigh]表数据]    脚本日期: 07/29/2014 15:44:57 ******/
    BEGIN TRANSACTION
    DECLARE @ReturnCode INT
    SELECT @ReturnCode = 0
    /****** 对象:  JobCategory [[Uncategorized (Local)]]]    脚本日期: 07/29/2014 15:44:57 ******/
    IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
    BEGIN
    EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    END
    
    DECLARE @jobId BINARY(16)
    EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'StatisticsforElapsedHigh', 
            @enabled=1, 
            @notify_level_eventlog=0, 
            @notify_level_email=0, 
            @notify_level_netsend=0, 
            @notify_level_page=0, 
            @delete_level=0, 
            @description=N'统计[MonitorElapsedHighSQL]库里的[ElapsedHigh]表各项数据', 
            @category_name=N'[Uncategorized (Local)]', 
            @owner_login_name=N'sa', @job_id = @jobId OUTPUT
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** 对象:  Step [execute usp_checkElapsedHighSQL script]    脚本日期: 07/29/2014 15:44:58 ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep  @job_name=N'StatisticsforElapsedHigh', @step_name=N'execute usp_StatisticsTask script', 
            @step_id=1, 
            @cmdexec_success_code=0, 
            @on_success_action=1, 
            @on_success_step_id=0, 
            @on_fail_action=2, 
            @on_fail_step_id=0, 
            @retry_attempts=0, 
            @retry_interval=0, 
            @os_run_priority=0, @subsystem=N'TSQL', 
            @command=N'exec [dbo].[usp_StatisticsTask] ',  --调用存储过程
            @database_name=N'MonitorElapsedHighSQL', 
            @flags=0
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_name=N'StatisticsforElapsedHigh', @name=N'Scheduleusp_StatisticsTask', 
        @enabled=1, 
            @freq_type=4, 
            @freq_interval=1, 
            @freq_subday_type=1, 
            @freq_subday_interval=1, 
            @freq_relative_interval=0, 
            @freq_recurrence_factor=0, 
            @active_start_date=20110224, 
            @active_end_date=99991231, 
            @active_start_time=235000, 
            @active_end_time=235959
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_name=N'StatisticsforElapsedHigh', @server_name = N'(local)'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    COMMIT TRANSACTION
    GOTO EndSave
    QuitWithRollback:
        IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
    EndSave:
    View Code

    第十步创建ScheduleSendStatisticsMail作业

    USE [msdb]
    GO
    /****** 对象:  Job [定时发统计邮件]    脚本日期: 07/29/2014 15:44:57 ******/
    BEGIN TRANSACTION
    DECLARE @ReturnCode INT
    SELECT @ReturnCode = 0
    /****** 对象:  JobCategory [[Uncategorized (Local)]]]    脚本日期: 07/29/2014 15:44:57 ******/
    IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
    BEGIN
    EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    END
    
    DECLARE @jobId BINARY(16)
    EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'ScheduleSendStatisticsMail', 
            @enabled=1, 
            @notify_level_eventlog=0, 
            @notify_level_email=0, 
            @notify_level_netsend=0, 
            @notify_level_page=0, 
            @delete_level=0, 
            @description=N'定时发统计邮件', 
            @category_name=N'[Uncategorized (Local)]',  
            @owner_login_name=N'sa', @job_id = @jobId OUTPUT
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** 对象:  Step [execute usp_checkElapsedHighSQL script]    脚本日期: 07/29/2014 15:44:58 ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep  @job_name=N'ScheduleSendStatisticsMail', @step_name=N'execute usp_SendStatisticsMail script', 
            @step_id=1, 
            @cmdexec_success_code=0, 
            @on_success_action=1, 
            @on_success_step_id=0, 
            @on_fail_action=2, 
            @on_fail_step_id=0, 
            @retry_attempts=0, 
            @retry_interval=0, 
            @os_run_priority=0, @subsystem=N'TSQL', 
            @command=N'exec  [dbo].[usp_SendStatisticsMail]',  --调用存储过程
            @database_name=N'MonitorElapsedHighSQL', 
            @flags=0
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_name=N'ScheduleSendStatisticsMail', @name=N'Scheduleusp_SendStatisticsMail', 
        @enabled=1, 
            @freq_type=4, 
            @freq_interval=1, 
            @freq_subday_type=1, 
            @freq_subday_interval=1, 
            @freq_relative_interval=0, 
            @freq_recurrence_factor=0, 
            @active_start_date=20110224, 
            @active_end_date=99991231, 
            @active_start_time=235500, 
            @active_end_time=235959
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_name=N'ScheduleSendStatisticsMail', @server_name = N'(local)'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    COMMIT TRANSACTION
    GOTO EndSave
    QuitWithRollback:
        IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
    EndSave:
    View Code

    原理解释:

    AutocaptureElapsedHighSQL作业每隔一分钟调用[usp_checkElapsedHighSQL]存储过程,而[usp_checkElapsedHighSQL]存储过程又会调用

    sp_who3存储过程获取一些当前线上环境的信息,被记录到[ElapsedHigh]表里

    ResetcheckElapsedHighSQLtbname作业会在每天的23点59分执行,调用[usp_Resettbname]存储过程, [usp_Resettbname]存储过程会将[ElapsedHigh]表

    的表名修改为:表名+当天日期,例如:ElapsedHigh2015-6-19 ,这样就进行了归档

    [usp_checkElapsedHighSQL] 存储过程有两种调用方式,一种是传入NULL,那么[usp_checkElapsedHighSQL] 存储过程就会抓取最耗时的那个session

    如果传入spid,那么就会显示那个spid的session

    --调用示例
    --不提供参数,抓取最耗时的一个SQL
    EXEC [MonitorElapsedHighSQL].[dbo].[usp_checkElapsedHighSQL] NULL
    
    
    --提供sessionsid参数,抓取那个sessionid相关的SQL
    EXEC [MonitorElapsedHighSQL].[dbo].[usp_checkElapsedHighSQL] 182

    StatisticsforElapsedHigh作业每天会在23点50分对[ElapsedHigh]表里的数据进行统计,把数据放进去五张统计表里

    ScheduleSendStatisticsMail作业会取出五张统计表里的数据并发送邮件,让DBA知道当天数据库有哪些慢SQL

    效果

    USE [sss]
    GO
    
    WHILE 1=1
    BEGIN
    DECLARE @test NVARCHAR(100)
    SET @test='你好'
    DECLARE @id int
    SET @id=2
    SELECT * FROM [sss].[dbo].[test] WHERE [id]=@id
    EXEC [dbo].[aa] @test =@test
    EXEC [dbo].[ab] @id=@id
    
    END
    SELECT * FROM [dbo].[ElapsedHigh]
    go

    可以看到,参数也能抓取到,一般依靠sys.dm_exec_sql_text视图和sys.[fn_get_sql]()视图是无法获取到参数的

    SQL Server profiler也是,它是整个RPC和Statement去抓

    而且还会抓取当时的XML执行计划,点击它就能显示图形化的执行计划,这样对分析当时语句的执行情况非常有帮助

    邮件效果


    总结

    目前脚本还是比较简单,后续还需要对各个数据库服务器的统计数据进行汇总,用web页面显示,这样即使数据库服务器再多也可以一目了然

    每天通过发邮件,把统计表的内容发邮件给开发人员,指导他们调整SQL,减轻DBA的一些工作量

    若有遗漏或失误,请留言回复,谢谢!

    如有不对的地方,欢迎大家拍砖o(∩_∩)o 

  • 相关阅读:
    vs2010 在函数级别设置优化
    从快速排序开始的代码演化
    pocket API学习笔记
    工作笔记:复制文件--从windows到ubuntu,再到fedora
    Win10 64位 Apache 2.4+MySQL 5.7+PHP 7环境搭建
    Json简介
    TCP/IP 协议详解和运作过程
    PHP 编程中 10 个最常见的错误,你犯过几个?
    php中的扩展解析
    php.ini设置详解
  • 原文地址:https://www.cnblogs.com/lyhabc/p/4587811.html
Copyright © 2011-2022 走看看