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

SQL Server 快速取得所有使用者表空間佔用:sp_MSforeachtable + sp_spaceused 批次統計

     編輯:關於SqlServer

前言

DBA 常需快速掌握全庫各表大小、列數、索引大小、未使用空間,以規劃歸檔、分割、壓縮策略。本文提供一支儲存程序,利用未文件化但廣泛使用的 sp_MSforeachtable 批次呼叫 sp_spaceused,結果寫入暫存表供即時查詢。

完整程式碼


CREATE PROCEDURE dbo.sp_get_table_space_info
AS
BEGIN
    SET NOCOUNT ON;

    -- 1. 建立結果暫存表 (若不存在)
    IF NOT EXISTS (SELECT * FROM sysobjects WHERE xtype = 'U' AND name = 'TableSpaceInfo')
    BEGIN
        CREATE TABLE TableSpaceInfo (
            name        VARCHAR(255),   -- 表名
            rows        BIGINT,         -- 列數
            reserved    VARCHAR(20),    -- 總保留空間 (含索引)
            data        VARCHAR(20),    -- 資料空間
            index_size  VARCHAR(20),    -- 索引空間
            unused      VARCHAR(20)     -- 未使用空間
        );
    END

    -- 2. 清空舊資料
    DELETE FROM TableSpaceInfo;

    -- 3. 批次執行 sp_spaceused
    EXEC sp_MSforeachtable @command1 = "INSERT INTO TableSpaceInfo EXEC sp_spaceused '?'";

    -- 4. 完成,直接查詢 TableSpaceInfo 即可
    -- SELECT * FROM TableSpaceInfo ORDER BY CAST(REPLACE(reserved, ' KB', '') AS BIGINT) DESC;
END
GO

使用方式


-- 1. 執行一次統計
EXEC sp_get_table_space_info;

-- 2. 查詢結果 (依總空間降冪)
SELECT
    name,
    rows,
    reserved,
    data,
    index_size,
    unused
FROM TableSpaceInfo
ORDER BY CAST(REPLACE(reserved, ' KB', '') AS BIGINT) DESC;

-- 3. 進階分析範例
-- 前 10 大表
SELECT TOP 10 * FROM TableSpaceInfo ORDER BY CAST(REPLACE(reserved, ' KB', '') AS BIGINT) DESC;

-- 索引佔比超過 50% 的表 (可能需壓縮/重建)
SELECT name, index_size, data,
       CAST(REPLACE(index_size, ' KB', '') AS FLOAT) / NULLIF(CAST(REPLACE(data, ' KB', '') AS FLOAT), 0) * 100 AS idx_data_ratio_pct
FROM TableSpaceInfo
WHERE CAST(REPLACE(data, ' KB', '') AS BIGINT) > 0
  AND CAST(REPLACE(index_size, ' KB', '') AS FLOAT) / CAST(REPLACE(data, ' KB', '') AS FLOAT) > 0.5
ORDER BY idx_data_ratio_pct DESC;

-- 空表 (rows=0 但保留空間>0) 清理候選
SELECT * FROM TableSpaceInfo WHERE rows = 0 AND CAST(REPLACE(reserved, ' KB', '') AS BIGINT) > 0;

取得整個資料庫大小


EXEC sp_spaceused;  -- 不帶參數 = 目前資料庫總覽

注意事項與替代方案

面向 說明
sp_MSforeachtable 未文件化 Microsoft 保留變更權利,但 SQL 2000~2022 皆穩定存在。生產核心流程建議改用 sys.tables 游標或動態 SQL 迴圈。
結果單位為 KB 字串 reserved 等欄位為 VARCHAR 含 ' KB' 後綴,排序/運算需 CAST(REPLACE(..., ' KB', '') AS BIGINT)。
大型資料庫耗時 逐表執行 sp_spaceused 需掃描配置頁,百萬列大表可能耗秒級。建議離峰執行或僅抽樣核心表。
替代:DMV 快速估算 sys.dm_db_partition_stats 可秒級彙總全庫表大小,無需掃描頁面,適合高頻監控。
SELECT OBJECT_NAME(object_id) AS name, SUM(row_count) AS rows, SUM(in_row_reserved_page_count)*8 AS reserved_kb ... FROM sys.dm_db_partition_stats GROUP BY object_id;

DMV 版本 (推薦用於自動化監控)


SELECT
    OBJECT_NAME(ps.object_id) AS TableName,
    SUM(ps.row_count) AS RowCount,
    SUM(ps.in_row_reserved_page_count) * 8.0 / 1024 AS Reserved_MB,
    SUM(ps.in_row_used_page_count) * 8.0 / 1024 AS Data_MB,
    (SUM(ps.in_row_reserved_page_count) - SUM(ps.in_row_used_page_count)) * 8.0 / 1024 AS Unused_MB
FROM sys.dm_db_partition_stats ps
JOIN sys.tables t ON ps.object_id = t.object_id
WHERE t.type = 'U'
GROUP BY ps.object_id
ORDER BY Reserved_MB DESC;

結語

sp_MSforeachtable + sp_spaceused 是快速取得表級空間佔用的經典組合,適合臨時分析、一次性報表。自動化監控、大型資料庫、高頻需求請改用 sys.dm_db_partition_stats DMV,效能差異可達 100 倍以上。建議兩套腳本並存:DMV 做日常巡檢,sp_spaceused 做深度驗證。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved