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

第三步创建[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

第四步创建[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

第五步创建[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

第六步创建[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

第七步创建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:

第八步创建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:

第九步创建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:

第十步创建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:

原理解释:

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]

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 

SQL Server定时自动抓取耗时SQL并归档数据发邮件脚本分享的更多相关文章

  1. SQL Server定时自动抓取耗时SQL并归档数据脚本分享

    原文:SQL Server定时自动抓取耗时SQL并归档数据脚本分享 SQL Server定时自动抓取耗时SQL并归档数据脚本分享 第一步建库 USE [master] GO CREATE DATABA ...

  2. SQL server 定时自动执行SQL存储过程

    当一个存储过程是为了生成报表,并且是周期性的,则不需要人工干预,由SQL作业定时自动执行些SQL存储过程即可. 本示例,假设已需要定时执行的存储过程为:Pr_test 工具/原料 SQL Server ...

  3. SQL Server 定时自动备份数据库

    在SQL Server中出于数据安全的考虑,所以需要定期的备份数据库,这篇文章介绍使用SQL Server 数据库代理中的作业定时自动备份数据库. 1.启动SQL Server代理服务,如下图: 绿色 ...

  4. SQL Server通过函数把逗号分隔的字符串拆分成数据列表的脚本-干货

    CREATE FUNCTION [dbo].[Split](@separator VARCHAR(64)=',',@string NVARCHAR(MAX))  RETURNS @ResultTab ...

  5. scrapy自动抓取蛋壳公寓最新房源信息并存入sql数据库

    利用scrapy抓取蛋壳公寓上的房源信息,以北京市为例,目标url:https://www.dankegongyu.com/room/bj 思路分析 每次更新最新消息,都是在第一页上显示,因此考虑隔一 ...

  6. sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取

    原文:sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取 在多人开发中最头疼的是人少事多没有时间进行codereview,本来功能都没时间写,哪有时间来开会细细来分析代码.软件能跑就行, ...

  7. SQL Server镜像自动生成脚本

    SQL Server镜像自动生成脚本 镜像的搭建非常繁琐,花了一点时间写了这个脚本,方便大家搭建镜像 执行完这个镜像脚本之后,最好在每台机器都绑定一下hosts文件,不然的话,镜像可能会不work 1 ...

  8. SQL Server 2012 自动增长列,值跳跃问题

    介绍 从 SQL Server 2012 版本开始, 当SQL Server 实例重启之后,表格的自动增长列的值会发生跳跃,而具体的跳跃值的大小是根据增长列的数据类型而定的.如果数据类型是 整型(in ...

  9. SQL Server 2012 自动增长列,值跳跃问题(自增增加1000)

    介绍 从 SQL Server 2012 版本开始, 当SQL Server 实例重启之后,表格的自动增长列的值会发生跳跃,而具体的跳跃值的大小是根据增长列的数据类型而定的.如果数据类型是 整型(in ...

随机推荐

  1. windows下ThinkPHP3.2.3使用memcache缓存

    准备 要使用memcache,首先要安装配置好memcache服务memcached: 下载http://downloads.northscale.com/memcached-win64-1.4.4- ...

  2. day4(homework)

    第八单元 1) 将用户信息数据库文件和组信息数据库文件纵向合并为一个文件/1.txt(覆盖) 2) 将用户信息数据库文件和用户密码数据库文件纵向合并为一个文件/2.txt(追加) 3) 将/1.txt ...

  3. UVA 11768 Lattice Point or Not(扩展欧几里德)

    将直线转化为ax + by = c的形式,然后扩展欧几里得求在[x1, x2]之间的解 对直线与坐标轴平行的特判 调试了好长时间,注意: 1 正负数转化为整型的处理 2 注意判断有无解 #includ ...

  4. Win10 UI入门 SliderRectangle

    看了@段博琼大哥导航滑动的思路,自己又做了一个类似与黄油相机里面的一个功能 <Grid x:Name="> <Grid.ColumnDefinitions> < ...

  5. Express URL跳转(重定向)的实现

    Express URL跳转(重定向)的实现   Express是一个基于Node.js实现的Web框架,其响应HTTP请求的response对象中有两个用于URL跳转方法res.location()和 ...

  6. jq冒泡之——点击其他地方隐藏

    e.stopPropagetion(); <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  7. 安装maven编译环境

    安装maven编译环境 1.默认已经装好yum并配置好yum源(推荐使用163yum源) 2.安装JDK 3.安装相关依赖环境(root用户登陆) yum install -y cmake lzo-d ...

  8. 设置NotePad++设置"不打开上次关闭的文件"

    notepad++是一个很好的记事本工具,但是默认会记录上次打开时未关闭的文件,但是实际上用起来并不方便, 可以按照下面的方式去除,notepad++版本:v6.6.2,os:win7 64位 按照以 ...

  9. Qt中 QString 和int, char等的“相互”转换

    转载:http://blog.csdn.net/ei__nino/article/details/7297791 Qt中 int ,float ,double转换为QString 有两种方法 1.使用 ...

  10. SOAPUI使用教程-MockService脚本概述

    虽然静态MockOperation和MockResponse模型可以给你一定的灵活性,更多的动态行为添加到您的服务让您更模拟复杂的服务功能是很有用的.例如,你可能想: 从请求到响应传输值,修改它们的值 ...