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

SQL Server 實作每日統計資料表新增列數與儲存空間變化

     編輯:關於SqlServer

前言

在資料庫維運管理中,掌握資料表每日的成長趨勢(新增列數、資料空間、索引空間變化)對於容量規劃、效能調校與異常偵測至關重要。本文提供一套完整的 T-SQL 解決方案,透過排程作業自動記錄每日空間使用情況,並示範如何查詢增量變化。

實作步驟

1. 建立統計資料儲存表

首先建立一張表,用於保存每次掃描的資料表空間資訊,包含列數、保留空間、資料大小、索引大小與未使用空間(單位皆為 KB)。

CREATE TABLE [dbo].[t_rpt_table_spaceinfo](
    [table_name] [sysname] NOT NULL,
    [record_date] [date] NOT NULL,
    [record_time] [time](7) NOT NULL,
    [rows_count] [bigint] NULL,
    [reserved] [bigint] NULL,
    [data_size] [bigint] NULL,
    [index_size] [bigint] NULL,
    [unused] [bigint] NULL,
    CONSTRAINT [PK_t_rpt_table_spaceinfo] PRIMARY KEY CLUSTERED 
    (
        [table_name] ASC,
        [record_date] ASC,
        [record_time] ASC
    )
)

2. 建立 SQL Server Agent 作業,每日自動收集

新增一個作業,排程於每天凌晨執行一次。作業步驟使用游標遍歷所有使用者資料表(sys.tables),呼叫 sp_spaceused 取得空間資訊,寫入暫存表後再批次轉入正式統計表。

SET NOCOUNT ON;

/* 建立暫存表存放 sp_spaceused 回傳結果 */
CREATE TABLE #tablespaceinfo (
    nameinfo VARCHAR(500),
    rowsinfo BIGINT,
    reserved VARCHAR(20),
    datainfo VARCHAR(20),
    index_size VARCHAR(20),
    unused VARCHAR(20)
);

DECLARE @tablename VARCHAR(255);

/* 使用游標逐一處理每張使用者資料表 */
DECLARE Info_cursor CURSOR FOR
    SELECT '[' + [name] + ']' FROM sys.tables WHERE type = 'U';

OPEN Info_cursor;
FETCH NEXT FROM Info_cursor INTO @tablename;

WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO #tablespaceinfo EXEC sp_spaceused @tablename;
    FETCH NEXT FROM Info_cursor INTO @tablename;
END

/* 將暫存資料轉型並寫入正式統計表 */
INSERT INTO t_rpt_table_spaceinfo (
    record_date, record_time, [table_name], [rows_count],
    reserved, [data_size], index_size, unused
)
SELECT 
    CONVERT(date, GETDATE()),
    CONVERT(varchar(8), GETDATE(), 114),
    nameinfo,
    rowsinfo,
    CAST(REPLACE(reserved, 'KB', '') AS BIGINT),
    CAST(REPLACE(datainfo, 'KB', '') AS BIGINT),
    CAST(REPLACE(index_size, 'KB', '') AS BIGINT),
    CAST(REPLACE(unused, 'KB', '') AS BIGINT)
FROM #tablespaceinfo;

CLOSE Info_cursor;
DEALLOCATE Info_cursor;
DROP TABLE #tablespaceinfo;

3. 查詢每日增量變化

利用 ROW_NUMBER() 視窗函數為同一資料表的記錄依時間排序編號,再自我聯結比較相鄰兩筆記錄,即可得到該時段內的新增列數與空間增長量。

;WITH table_spaceinfo AS (
    SELECT 
        record_date, record_time, table_name, rows_count,
        reserved, data_size, index_size, unused,
        ROW_NUMBER() OVER (PARTITION BY table_name ORDER BY record_date, record_time) AS list_no
    FROM t_rpt_table_spaceinfo
)
SELECT 
    _a.table_name AS 表名,
    CONVERT(varchar(20), _a.record_date) + ' ' + CONVERT(varchar(8), _a.record_time) + '~~' +
    CONVERT(varchar(20), _b.record_date) + ' ' + CONVERT(varchar(8), _b.record_time) AS [時間段範圍],
    _b.rows_count - _a.rows_count AS [新增列數],
    _b.data_size - _a.data_size AS [新增資料空間(KB)]
FROM table_spaceinfo _a
JOIN table_spaceinfo _b
    ON _a.table_name = _b.table_name
    AND _a.list_no = _b.list_no - 1
ORDER BY [時間段範圍];

應用場景與效益

  • 容量預測:依歷史成長趨勢估算未來磁碟需求。
  • 異常偵測:若某日新增列數或空間暴增,可能代表 ETL 異常、資料重複匯入或索引碎片嚴重。
  • 效能基準:配合索引維護排程,觀察重建索引前後的空間釋放效果。

注意事項

  1. sp_spaceused 回傳單位為 KB,已在寫入時移除單位字串並轉為 BIGINT,方便直接運算。
  2. 主鍵設計為 (table_name, record_date, record_time),確保同一資料表同一天可記錄多次(如需更高頻率)。
  3. 若資料表極多,游標迴圈可能耗時較久,可考慮改用 sp_msforeachtable 或動態 SQL 批次處理以提升效能。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved