筆者須要收集的SQL Server計數器包括:SQL Server計數器屬性詳解html
一、 生產服務器經過ODBC開發數據庫互聯ODBC配置訪問監控監控服務器的SQLPerfData,將數據寫入該數據庫。詳情請見計數器部署 SQL Server性能計數器部署(批量)算法
二、 經過做業調用存儲過程spb_Perf_CounterDataCollect將數據從SQLPerfData寫入SQLPerfDataStat數據庫。數據庫
1 /****************************** 功能描述:<性能計數器15秒統計> 2 * 建立者:<HuangCH〉 3 * 建立日期:<2014-09-22> 4 * 備註說明:<根據具體業務而定,每分鐘一次> 5 ########## 6 Change Log 7 ########## 8 Date Changer Description 9 -------------------------------------------------- 10 <2014-09-22> <HuangCH> <新建> 11 -------------------------------------------------- 12 ***************************/ 13 ALTER PROC [dbo].[spb_Perf_CounterDataCollect] 14 as 15 --定義當前時間 16 SET NOCOUNT ON 17 DECLARE @FifteenSec DATETIME 18 ,@OneMinute DATETIME 19 ,@FiveMinute DATETIME 20 ,@HalfHour DATETIME 21 ,@OneHour DATETIME 22 ,@SixHour DATETIME 23 ,@OldFifteenSec DATETIME 24 25 DECLARE @MaxRecordIndex INT 26 DECLARE @MinRecordIndex INT 27 28 SET @FifteenSec=CONVERT(VARCHAR(23),GETDATE(),120) 29 SET @OneMinute=CONVERT(VARCHAR(16),@FifteenSec,120) 30 SET @FiveMinute=Dateadd(mi,Datepart(mi,@OneMinute) / 5 * 5 - Datepart(mi,@OneMinute),@OneMinute) 31 SET @HalfHour=Dateadd(mi,Datepart(mi,@OneMinute) / 30 * 30 - Datepart(mi,@OneMinute),@OneMinute) 32 SET @OneHour=CONVERT(VARCHAR(14),@FifteenSec,120)+'00:00' 33 SET @SixHour=Dateadd(HH,Datepart(mi,@OneHour) / 30 * 30 - Datepart(mi,@OneHour),@OneHour) 34 35 ------進入循環收集處理----------------------------------------------- 36 37 DECLARE @MachineName SYSNAME 38 DECLARE CUR_COUNTERDATA CURSOR FOR 39 SELECT DISTINCT MachineName 40 FROM [dbo].[CounterDetails_Collect] WITH(NOLOCK) 41 OPEN CUR_COUNTERDATA 42 FETCH NEXT FROM CUR_COUNTERDATA INTO @MachineName 43 44 WHILE @@FETCH_STATUS=0 45 BEGIN 46 47 IF NOT EXISTS (SELECT TOP 1 1 FROM [dbo].[CounterDetails_Dts] WHERE [MachineName]=@MachineName) 48 BEGIN 49 --添加未插入的數據 50 51 INSERT INTO [dbo].[CounterDetails_Dts] 52 SELECT @MachineName,0,@FifteenSec,@OneMinute,@FiveMinute,@HalfHour,@OneHour,@SixHour,@OneMinute,@OneMinute,@FifteenSec 53 54 FETCH NEXT FROM CUR_COUNTERDATA INTO @MachineName 55 CONTINUE 56 END 57 58 SELECT @MinRecordIndex=[LastRecordIndex],@OldFifteenSec=LastFifteenSec FROM [dbo].[CounterDetails_Dts] WITH(NOLOCK) 59 WHERE [MachineName]=@MachineName 60 61 62 IF DATEDIFF(MI,@OldFifteenSec,@FifteenSec)>25 63 BEGIN 64 SET @MinRecordIndex=0 65 END 66 67 SELECT @MaxRecordIndex=MAX([RecordIndex]),@FifteenSec=MAX(CONVERT(DATETIME,LEFT(A.CounterDateTime,23))) 68 FROM [SQLPerfData].[dbo].[CounterData] A WITH(NOLOCK) 69 WHERE CounterID=(SELECT TOP 1 CounterID FROM [dbo].[CounterDetails_Collect] B WITH(NOLOCK) WHERE B.MachineName=@MachineName) 70 AND [RecordIndex]>@MinRecordIndex 71 72 --若因爲重啓致使index恢復,則要從新計算 73 IF @MaxRecordIndex IS NULL 74 BEGIN 75 76 SET @MaxRecordIndex=@MinRecordIndex--上次最大值 77 SELECT @MinRecordIndex=NumberOfRecords FROM --當前最大值 78 ( 79 SELECT ROW_NUMBER() OVER(ORDER BY LogStartTime DESC) ROW_ID,NumberOfRecords 80 FROM [SQLPerfData].[dbo].[DisplayToID] 81 WHERE GUID IN( 82 SELECT DISTINCT A.GUID FROM [SQLPerfData].[dbo].[CounterData] A WITH(NOLOCK) 83 JOIN [dbo].[CounterDetails_Collect] B WITH(NOLOCK) ON A.CounterID=B.CounterID 84 WHERE B.MachineName=@MachineName) 85 ) AA 86 WHERE ROW_ID=1 87 88 --刪除已經收集的 89 DELETE A FROM [SQLPerfData].[dbo].[CounterData] A WITH(NOLOCK) 90 JOIN [dbo].[CounterDetails_Collect] B WITH(NOLOCK) ON A.CounterID=B.CounterID 91 WHERE A.[RecordIndex]>@MinRecordIndex AND A.[RecordIndex]<=@MaxRecordIndex AND B.MachineName=@MachineName 92 93 --恢復當前有效值 94 SET @MaxRecordIndex=@MinRecordIndex 95 SET @MinRecordIndex=0 96 END 97 98 99 IF @MaxRecordIndex IS NOT NULL 100 BEGIN 101 BEGIN TRY 102 --BEGIN TRAN 103 ----收集 104 INSERT INTO [dbo].[CounterData_FifteenSeconds](CounterID,CounterDateTime,CounterValue) 105 SELECT A.CounterID,CONVERT(DATETIME,LEFT(A.CounterDateTime,23)),A.CounterValue 106 FROM [SQLPerfData].[dbo].[CounterData] A WITH(NOLOCK) 107 JOIN [dbo].[CounterDetails_Collect] B WITH(NOLOCK) ON A.CounterID=B.CounterID 108 WHERE A.[RecordIndex]>@MinRecordIndex AND A.[RecordIndex]<=@MaxRecordIndex AND B.MachineName=@MachineName 109 110 UPDATE [dbo].[CounterDetails_Dts] 111 SET LastFifteenSec=@FifteenSec,[LastRecordIndex]=@MaxRecordIndex 112 WHERE MachineName=@MachineName 113 --COMMIT 114 END TRY 115 BEGIN CATCH 116 IF @@TRANCOUNT>0 117 COMMIT; 118 --THROW 119 END CATCH 120 121 --更新 122 /* 123 UPDATE [dbo].[CounterDetails_Dts] 124 SET LastFifteenSec=@FifteenSec,[LastRecordIndex]=@MaxRecordIndex 125 WHERE [CounterID]=@CounterID */ 126 127 --刪除30分鐘內的數據 128 129 130 END 131 132 DELETE A 133 FROM [CounterData_FifteenSeconds] A 134 JOIN [dbo].[CounterDetails_Collect] B WITH(NOLOCK) ON A.CounterID=B.CounterID 135 WHERE B.MachineName=@MachineName AND CounterDateTime<DATEADD(WEEK,-1,@FifteenSec) 136 137 FETCH NEXT FROM CUR_COUNTERDATA INTO @MachineName 138 END 139 CLOSE CUR_COUNTERDATA 140 DEALLOCATE CUR_COUNTERDATA 141 142 --監控
三、 彙總取均值,將15秒鐘數據彙總成1分鐘,5分鐘,半小時,一小時,六小時數據。各個粒度的數據用於不一樣時段的報表顯示。例如1分鐘數據彙總可用於顯示一天內的報表,一個月的報表則須要一小時的數據才能正常顯示。經過做業調用spb_Perf_CounterDataDts彙總。服務器
1 /****************************** 功能描述:<性能計數器15秒統計> 2 * 建立者:<HuangCH〉 3 * 建立日期:<2014-09-22> 4 * 備註說明:<根據具體業務而定,每分鐘一次> 5 ########## 6 Change Log 7 ########## 8 Date Changer Description 9 -------------------------------------------------- 10 <2014-09-22> <HuangCH> <新建> 11 -------------------------------------------------- 12 ***************************/ 13 ALTER PROC [dbo].[spb_Perf_CounterDataDts] 14 as 15 --定義當前時間 16 SET NOCOUNT ON 17 DECLARE @OneMinute DATETIME 18 ,@FiveMinute DATETIME 19 ,@HalfHour DATETIME 20 ,@OneHour DATETIME 21 ,@SixHour DATETIME 22 DECLARE @OldOneMinute datetime 23 ,@OldFiveMinute datetime 24 ,@OldHalfHour datetime 25 ,@OldOneHour datetime 26 ,@OldSixHour datetime 27 ,@OldFifteenSec DATETIME 28 29 --MachineName 30 DECLARE @MachineName SYSNAME 31 32 DECLARE CUR_CounterDataDts CURSOR FOR 33 34 SELECT DISTINCT MachineName 35 FROM [dbo].[CounterDetails_Dts] WITH(NOLOCK) 36 OPEN CUR_CounterDataDts 37 FETCH NEXT FROM CUR_CounterDataDts INTO @MachineName 38 39 WHILE @@FETCH_STATUS=0 40 BEGIN 41 SELECT 42 @OldFifteenSec= LastFifteenSec, 43 @OldOneMinute= LastOneMinute, 44 @OldFiveMinute= LastFiveMinute, 45 @OldHalfHour=LastHalfHour, 46 @OldOneHour=LastOneHour, 47 @OldSixHour=LastSixHour 48 FROM [dbo].[CounterDetails_Dts] WITH(NOLOCK) 49 WHERE MachineName=@MachineName 50 51 SET @OneMinute=CONVERT(VARCHAR(16),@OldFifteenSec,120) 52 SET @FiveMinute=Dateadd(mi,Datepart(mi,@OneMinute) / 5 * 5 - Datepart(mi,@OneMinute),@OneMinute) 53 SET @HalfHour=Dateadd(mi,Datepart(mi,@OneMinute) / 30 * 30 - Datepart(mi,@OneMinute),@OneMinute) 54 SET @OneHour=CONVERT(VARCHAR(14),@OneMinute,120)+'00:00' 55 SET @SixHour=Dateadd(HH,Datepart(HH,@OneHour) / 6 * 6 -Datepart(hh,@OneHour),@OneHour) 56 57 --超過60分鐘未收集,則只收集60分鐘之內的數據 58 IF DATEDIFF(MI,@OldOneMinute,@OneMinute)>60 59 BEGIN 60 SET @OldOneMinute=DATEADD(MI,-60,@OneMinute) 61 END 62 63 UPDATE [dbo].[CounterDetails_Dts] 64 SET LastOneMinute=@OneMinute,LastFiveMinute=@FiveMinute,LastHalfHour=@HalfHour,LastOneHour=@OneHour,LastSixHour=@SixHour 65 WHERE MachineName=@MachineName 66 67 BEGIN TRY 68 --一分鐘 69 INSERT INTO [dbo].[CounterData_OneMinute] 70 SELECT A.CounterID,CONVERT(VARCHAR(16),A.CounterDateTime,120),AVG(A.CounterValue) 71 FROM [dbo].[CounterData_FifteenSeconds] A WITH(NOLOCK) 72 JOIN [dbo].[CounterDetails_Collect] B WITH(NOLOCK) ON A.CounterID=B.CounterID 73 WHERE B.MachineName=@MachineName AND A.CounterDateTime <= @OneMinute And A.CounterDateTime > @OldOneMinute 74 GROUP BY A.CounterID,CONVERT(VARCHAR(16),A.CounterDateTime,120) 75 76 END TRY 77 BEGIN CATCH 78 IF @@ROWCOUNT>0 79 COMMIT 80 END CATCH 81 BEGIN TRY 82 --五分鐘 83 INSERT INTO [dbo].[CounterData_FiveMinute] 84 SELECT A.CounterID,Dateadd(mi,Datepart(mi,A.CounterDateTime) / 5 * 5 - Datepart(mi,A.CounterDateTime),CONVERT(DATETIME,CONVERT(CHAR(16),A.CounterDateTime,120))),AVG(A.CounterValue) 85 FROM [dbo].[CounterData_OneMinute] A WITH(NOLOCK) 86 JOIN [dbo].[CounterDetails_Collect] B WITH(NOLOCK) ON A.CounterID=B.CounterID 87 WHERE B.MachineName=@MachineName AND A.CounterDateTime <= @FiveMinute And A.CounterDateTime > @OldFiveMinute 88 GROUP BY A.CounterID,Dateadd(mi,Datepart(mi,A.CounterDateTime) / 5 * 5 - Datepart(mi,A.CounterDateTime),CONVERT(DATETIME,CONVERT(CHAR(16),A.CounterDateTime,120))) 89 90 END TRY 91 BEGIN CATCH 92 IF @@ROWCOUNT>0 93 COMMIT 94 95 END CATCH 96 BEGIN TRY 97 --半個小時 98 INSERT INTO [dbo].[CounterData_HalfHour] 99 SELECT A.CounterID,Dateadd(mi,Datepart(mi,A.CounterDateTime) / 30 * 30 - Datepart(mi,A.CounterDateTime),CONVERT(DATETIME,CONVERT(CHAR(16),A.CounterDateTime,120))),AVG(A.CounterValue) 100 FROM [dbo].[CounterData_OneMinute] A WITH(NOLOCK) 101 JOIN [dbo].[CounterDetails_Collect] B WITH(NOLOCK) ON A.CounterID=B.CounterID 102 WHERE B.MachineName=@MachineName AND A.CounterDateTime <= @HalfHour And A.CounterDateTime > @OldHalfHour 103 GROUP BY A.CounterID,Dateadd(mi,Datepart(mi,A.CounterDateTime) / 30 * 30 - Datepart(mi,A.CounterDateTime),CONVERT(DATETIME,CONVERT(CHAR(16),A.CounterDateTime,120))) 104 105 END TRY 106 BEGIN CATCH 107 IF @@ROWCOUNT>0 108 COMMIT 109 END CATCH 110 111 BEGIN TRY 112 --一小時 113 INSERT INTO [dbo].[CounterData_OneHour] 114 SELECT A.CounterID,CONVERT(VARCHAR(14),A.CounterDateTime,120)+'00:00',AVG(A.CounterValue) 115 FROM [dbo].[CounterData_OneMinute] A WITH(NOLOCK) 116 JOIN [dbo].[CounterDetails_Collect] B WITH(NOLOCK) ON A.CounterID=B.CounterID 117 WHERE B.MachineName=@MachineName AND A.CounterDateTime <= @OneHour And A.CounterDateTime > @OldOneHour 118 GROUP BY A.CounterID,CONVERT(VARCHAR(14),A.CounterDateTime,120) 119 120 END TRY 121 BEGIN CATCH 122 IF @@ROWCOUNT>0 123 COMMIT 124 END CATCH 125 126 BEGIN TRY 127 --六小時 128 INSERT INTO [dbo].[CounterData_SixHour] 129 SELECT A.CounterID,Dateadd(HH,Datepart(HH,A.CounterDateTime) / 6 * 6 -Datepart(hh,A.CounterDateTime),A.CounterDateTime),AVG(A.CounterValue) 130 FROM [dbo].[CounterData_OneMinute] A WITH(NOLOCK) 131 JOIN [dbo].[CounterDetails_Collect] B WITH(NOLOCK) ON A.CounterID=B.CounterID 132 WHERE B.MachineName=@MachineName AND A.CounterDateTime <= @SixHour And A.CounterDateTime > @OldSixHour 133 GROUP BY A.CounterID,Dateadd(HH,Datepart(HH,A.CounterDateTime) / 6 * 6 -Datepart(hh,A.CounterDateTime),A.CounterDateTime) 134 END TRY 135 BEGIN CATCH 136 IF @@ROWCOUNT>0 137 COMMIT 138 END CATCH 139 FETCH NEXT FROM CUR_CounterDataDts INTO @MachineName 140 END 141 CLOSE CUR_CounterDataDts 142 DEALLOCATE CUR_CounterDataDts
四、 計算曆史數據爲基線數據,與當前數據對比。SQL Server基線算法(同比和環比)架構
如上圖所示,計數器架構分別存儲三個數據庫SQLPerfData、SQLPerfDataStat、SQLPerfDataStat_Histroy;這三個計數器的功能具體以下:ide
DisplayToID:計數器自動生成,記錄計數器啓動信息post
CounterDetails:計數器自動生成,記錄計數器的基本信息性能
CounterData:記錄計數器傳入的數據優化
基本信息模塊:spa
CounterDetails_Collect:用於同步 CounterDetails表數據,用於輪訓統計
CounterDetails_Collect_bak:無用計數器備份
CounterDetails_Dts:統計傳輸控制表,以服務器爲單位,記錄服務器統計傳輸時間。
CounterDetails_Report:同步CounterDetails_Collect表信息,經過優化,用於報表顯示做用。
數據模塊:
CounterData_FifteenSeconds:15秒數據收集,用於同步CounterData表數據。
CounterData_OneMinute:一分鐘數據收集,15秒數據均值計算而成;適合查看當天數據。保留7天數據。
CounterData_FiveMinute:五分鐘數據收集,一分鐘數據均值計算而成;適合查看4天內數據。保留7天數據。
CounterData_HalfHour:30分鐘數據收集,一分鐘數據均值計算而成;適合查看一週內數據。保留7天數據。
CounterData_OneHour:一小時數據收集,一分鐘數據均值計算而成;適合查看一個月內數據。保留永久
CounterData_SixHour:六小時數據收集,一分鐘數據均值計算而成;適合查看一年內數據。保留永久
基線模塊:
CBaseCounterData_OneMinute:同比基線,能夠計算將來一週的數據走勢。保留7天數據。
RBaseCounterData_OneMinute:環比基線,能夠計算將來一天的數據走勢。保留7天數據。
手動維護模塊:
CounterTypeDetails:計數器類型和描述信息記錄表。
MonitorContorl:手動維護,計數器報警監控控制表。
CounterData_OneMinute_bak:一分鐘數據備份,保留永久。
CounterData_FiveMinute_bak:五分鐘數據備份,保留永久。
CounterData_HalfHour_bak:30分鐘數據備份,保留永久。
基線模塊:
CBaseCounterData_OneMinute_bak:同比基線備份,保留7天。
RBaseCounterData_OneMinute_bak:環比基線備份,保留7天。