首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

MSSQL 資料/日誌檔案成長監控系統:自動化收集、環比同比分析與 T-SQL/Oracle 差異對比

     編輯:關於SqlServer

部署磁碟空間監控後收到告警,但缺乏歷史成長資料無法判斷成因。本文實作一套自動化收集 sys.master_files 資訊、計算環比/同比成長率、支援趨勢分析的監控系統。

一、設計架構

  1. 儲存表 DiskCapacityHistory:記錄每日各資料庫檔案大小、成長類型、環比/同比
  2. 收集程序 sp_diskcapacity_cal:每日排程執行,寫入快照並計算成長率
  3. 排程作業:SQL Agent 每日固定時間 (如 02:00) 執行

二、核心物件建立腳本

1. 歷史資料表

USE msdb;
GO

IF OBJECT_ID('dbo.DiskCapacityHistory', 'U') IS NOT NULL
    DROP TABLE dbo.DiskCapacityHistory;
GO

CREATE TABLE dbo.DiskCapacityHistory
(
    Date_CD          INT           NOT NULL,  -- YYYYMMDD
    DataBaseID       INT           NOT NULL,
    FileID           INT           NOT NULL,
    DataBaseName     sysname       NOT NULL,
    LogicalName      VARCHAR(32)   NOT NULL,
    FileTypeDesc     NVARCHAR(60)  NOT NULL,  -- ROWS / LOG
    PhysicalName     NVARCHAR(260) NOT NULL,
    StateDesc        NVARCHAR(60)  NOT NULL,
    MaxSize          NVARCHAR(32)  NOT NULL,  -- 不允許增長 / 自動增長 / 具體 GB
    GrowthType       NVARCHAR(8)   NOT NULL,  -- 10% / 64MB
    IsReadOnly       INT           NOT NULL,
    IsPercentGrowth  SMALLINT      NOT NULL,
    Size             FLOAT         NOT NULL,  -- GB
    Growth_MOM_RAT   FLOAT         NULL,      -- 環比成長率 (%)
    Growth_YOY_RAT   FLOAT         NULL,      -- 同比成長率 (%)
    CONSTRAINT PK_DiskCapacityHistory PRIMARY KEY (Date_CD, DataBaseID, FileID)
);
GO

2. 收集與計算儲存程序 (SQL Server 2008+ MERGE 寫法)

CREATE OR ALTER PROCEDURE dbo.sp_diskcapacity_cal
AS
BEGIN
    SET NOCOUNT ON;

    -- 1. 插入今日快照
    INSERT INTO dbo.DiskCapacityHistory
    (Date_CD, DataBaseID, FileID, DataBaseName, LogicalName, FileTypeDesc,
     PhysicalName, StateDesc, MaxSize, GrowthType, IsReadOnly, IsPercentGrowth, Size)
    SELECT 
        CAST(REPLACE(CONVERT(CHAR(10), GETDATE(), 120), '-', '') AS INT),  -- Date_CD
        database_id, file_id, DB_NAME(database_id), name, type_desc,
        physical_name, state_desc,
        CASE 
            WHEN max_size = 0 THEN N'不允許增長'
            WHEN max_size = -1 THEN N'自動增長'
            ELSE LTRIM(STR(max_size * 8.0 / 1024 / 1024, 14, 2)) + 'GB'
        END,
        CASE 
            WHEN is_percent_growth = 1 THEN CAST(growth AS VARCHAR(10)) + '%'
            ELSE CAST(growth AS VARCHAR(10)) + 'MB'
        END,
        is_read_only, is_percent_growth,
        CAST(size * 8.0 / 1024 / 1024 AS DECIMAL(10,4))  -- Size (GB)
    FROM sys.master_files;

    -- 2. 計算環比 (MoM) 與同比 (YoY) 成長率
    -- 環比:今日 vs 上月同一天;同比:今日 vs 去年同一天
    ;WITH Today AS (
        SELECT * FROM dbo.DiskCapacityHistory 
        WHERE Date_CD = CAST(REPLACE(CONVERT(CHAR(10), GETDATE(), 120), '-', '') AS INT)
    ),
    PrevMonth AS (
        SELECT * FROM dbo.DiskCapacityHistory 
        WHERE Date_CD = CAST(REPLACE(CONVERT(CHAR(10), DATEADD(MONTH, -1, GETDATE()), 120), '-', '') AS INT)
    ),
    PrevYear AS (
        SELECT * FROM dbo.DiskCapacityHistory 
        WHERE Date_CD = CAST(REPLACE(CONVERT(CHAR(10), DATEADD(YEAR, -1, GETDATE()), 120), '-', '') AS INT)
    )
    MERGE INTO dbo.DiskCapacityHistory AS Target
    USING (
        SELECT 
            T.Date_CD, T.DataBaseID, T.FileID,
            CASE WHEN P.Size IS NULL OR P.Size = 0 THEN 0 
                 ELSE (T.Size - P.Size) / P.Size END AS Growth_MOM_RAT,
            CASE WHEN Y.Size IS NULL OR Y.Size = 0 THEN 0 
                 ELSE (T.Size - Y.Size) / Y.Size END AS Growth_YOY_RAT
        FROM Today T
        LEFT JOIN PrevMonth P 
            ON T.DataBaseID = P.DataBaseID AND T.FileID = P.FileID
        LEFT JOIN PrevYear Y 
            ON T.DataBaseID = Y.DataBaseID AND T.FileID = Y.FileID
    ) AS Source
    ON Target.Date_CD = Source.Date_CD 
       AND Target.DataBaseID = Source.DataBaseID 
       AND Target.FileID = Source.FileID
    WHEN MATCHED THEN UPDATE SET
        Target.Growth_MOM_RAT = Source.Growth_MOM_RAT,
        Target.Growth_YOY_RAT = Source.Growth_YOY_RAT;
END;
GO

三、SQL Server 2005 相容寫法 (無 MERGE)

-- 使用暫存表 + UPDATE 替代 MERGE
CREATE TABLE #GrowthCalc (
    Date_CD INT, DataBaseID INT, FileID INT, 
    Growth_MOM_RAT FLOAT, Growth_YOY_RAT FLOAT
);

INSERT INTO #GrowthCalc
SELECT T.Date_CD, T.DataBaseID, T.FileID,
    CASE WHEN P.Size IS NULL OR P.Size = 0 THEN 0 ELSE (T.Size - P.Size) / P.Size END,
    CASE WHEN Y.Size IS NULL OR Y.Size = 0 THEN 0 ELSE (T.Size - Y.Size) / Y.Size END
FROM dbo.DiskCapacityHistory T
LEFT JOIN dbo.DiskCapacityHistory P 
    ON T.DataBaseID = P.DataBaseID AND T.FileID = P.FileID
    AND T.Date_CD = CAST(REPLACE(CONVERT(CHAR(10), DATEADD(MONTH, 1, CAST(CAST(P.Date_CD AS CHAR(8)) AS DATE))), '-', '') AS INT)
LEFT JOIN dbo.DiskCapacityHistory Y 
    ON T.DataBaseID = Y.DataBaseID AND T.FileID = Y.FileID
    AND T.Date_CD = CAST(REPLACE(CONVERT(CHAR(10), DATEADD(YEAR, 1, CAST(CAST(Y.Date_CD AS CHAR(8)) AS DATE))), '-', '') AS INT)
WHERE T.Date_CD = CAST(REPLACE(CONVERT(CHAR(10), GETDATE(), 120), '-', '') AS INT);

UPDATE DCH
SET Growth_MOM_RAT = G.Growth_MOM_RAT, Growth_YOY_RAT = G.Growth_YOY_RAT
FROM dbo.DiskCapacityHistory DCH
JOIN #GrowthCalc G 
    ON DCH.Date_CD = G.Date_CD AND DCH.DataBaseID = G.DataBaseID AND DCH.FileID = G.FileID;

DROP TABLE #GrowthCalc;

四、T-SQL vs PL/SQL 日期轉換與分析函數差異對比

1. 日期 ↔ 整數轉換

操作T-SQL (SQL Server)PL/SQL (Oracle)
日期 → 整數 (YYYYMMDD)CAST(REPLACE(CONVERT(CHAR(10), GETDATE(), 120), '-', '') AS INT)TO_CHAR(SYSDATE, 'YYYYMMDD')
整數 → 日期CAST(CAST(Date_CD AS CHAR(8)) AS DATE)TO_DATE(Date_CD, 'YYYYMMDD')

結論:Oracle 語法更簡潔直觀,T-SQL 需多層嵌套轉換。

2. 環比/同比計算:LAG 分析函數優勢

Oracle 支援 LAG() OVER (PARTITION BY ... ORDER BY ...),單一查詢即可完成所有分組的環比同比,無需自我連接:

-- Oracle 風格 (單查詢搞定)
MERGE INTO TargetTable T
USING (
    SELECT 
        Date_CD, DataBaseID, FileID,
        (Size - LAG(Size) OVER (PARTITION BY DataBaseID, FileID ORDER BY Date_CD)) 
            / NULLIF(LAG(Size) OVER (PARTITION BY DataBaseID, FileID ORDER BY Date_CD), 0) AS Growth_MOM_RAT,
        (Size - LAG(Size, 12) OVER (PARTITION BY DataBaseID, FileID ORDER BY Date_CD)) 
            / NULLIF(LAG(Size, 12) OVER (PARTITION BY DataBaseID, FileID ORDER BY Date_CD), 0) AS Growth_YOY_RAT
    FROM DiskCapacityHistory
) S
ON (T.Date_CD = S.Date_CD AND T.DataBaseID = S.DataBaseID AND T.FileID = S.FileID)
WHEN MATCHED THEN UPDATE SET 
    T.Growth_MOM_RAT = S.Growth_MOM_RAT,
    T.Growth_YOY_RAT = S.Growth_YOY_RAT;

SQL Server 2012+ 也支援 LAG/LEAD,強烈建議升級後改寫,大幅簡化邏輯並提升效能。

五、擴充應用建議

  • 告警閾值:環比 > 20% 或同比 > 100% 發送郵件告警
  • 關聯業務:將成長率與部署上線、促銷活動、資料清洗排程關聯分析
  • 視覺化:Power BI / Grafana 連接 DiskCapacityHistory 繪製成長趨勢圖
  • 容量規劃:線性回歸預測 3/6/12 個月磁碟需求,提前採購擴容
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved