最近遇到一个小问题:为了保存以往的一些数据,间了大量临时表,导致SQLserver 数据增长过快,不得不想个办法监控磁盘空间使用情况。
网上一般有几种办法:
一是使用 dm_os_volume_stats函数,缺点是 无法获取非数据库所在的磁盘空间使用情况。
二是使用 Exec master.dbo.xp_fixeddrives ,缺点是只有磁盘空间使用情况,没有总容量。
三是使用xp_fixeddrives+xp_cmdshell,虽然有现成的语句,但过于复杂,而且打开cmdshell是存在一定的风险。
所以,可以简化操作如下:
1、使用dm_os_volume_stats函数,获得所有磁盘信息,若某个磁盘不在其中,则先增加一个临时数据库
例如,如果数据只存放在c\d盘,E盘没有数据库但用于备份,也需要监控,可以临时建立数据库(其他磁盘可参考):
USE [master]
GO
/****** Object: Database [TEMP_BT] Script Date: 2023/9/14 8:59:38 ******/
DROP DATABASE IF EXISTS [TEMP_BT]
GO
/****** Object: Database [TEMP_BT] Script Date: 2023/9/14 8:59:38 ******/
CREATE DATABASE [TEMP_BT]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'TEMP_BT', FILENAME = N'E:\DATA\TEMP_BT.mdf' , SIZE = 1024KB , MAXSIZE = UNLIMITED, FILEGROWTH = 16KB )
LOG ON
( NAME = N'TEMP_BT_log', FILENAME = N'E:\DATA\TEMP_BT_log.ldf' , SIZE = 1024KB , MAXSIZE = 2GB , FILEGROWTH = 16KB )
GO
2、用dm_os_volume_stats函数获取磁盘信息,这些语句已经有现成的:
(假设数据库用 Data)
drop table if exists [Data].[dbo].[T_diskspace]
go
WITH T1 AS (
SELECT DISTINCT
REPLACE(vs.volume_mount_point,':\','') AS Drive_Name ,
CAST(vs.total_bytes / 1024.0 / 1024 / 1024 AS NUMERIC(18,2)) AS Total_Space_GB ,
CAST(vs.available_bytes / 1024.0 / 1024 / 1024 AS NUMERIC(18,2)) AS Free_Space_GB
FROM sys.master_files AS f
outer APPLY sys.dm_os_volume_stats(f.database_id, f.file_id) AS vs
)
SELECT
GETDATE() as sdate,
Drive_Name,
Total_Space_GB,
Total_Space_GB-Free_Space_GB AS Used_Space_GB,
Free_Space_GB,
CAST(Free_Space_GB*100/Total_Space_GB AS NUMERIC(18,2)) AS Free_Space_Percent
into [Data].[dbo].[T_diskspace]
FROM T1
go
use [Data]
go
select * from [Data].[dbo].[T_diskspace]
go
完成后,如下图可见:
use [master]
go
DROP DATABASE IF EXISTS [TEMP_BT]
GO
以上数据获取后运行一次保存即可,以后无需运行
3、用 Exec master.dbo.xp_fixeddrives 监控磁盘空间情况即可。
use [Data]
go
select * from [Data].[dbo].[T_diskspace]
go
drop table if exists [dbo].[Temp_diskspace]
go
CREATE TABLE [dbo].[Temp_diskspace](
[Drive_name] [nvarchar](500) NULL,
[Free_Space] [numeric](20,2) NULL,
) ON [PRIMARY]
GO
insert into [Data].[dbo].[Temp_diskspace](Drive_Name,Free_Space)
Exec master.dbo.xp_fixeddrives
go
update [Data].[dbo].[T_diskspace] set sdate=GETDATE(),Free_Space_GB=cast(b.Free_Space/1024 as numeric(20,2))
from [Data].[dbo].[T_diskspace] a,[Data].[dbo].[Temp_diskspace] b
where a.Drive_Name=b.Drive_Name
go
update [Data].[dbo].[T_diskspace] set Used_Space_GB=Total_Space_GB-Free_Space_GB,
Free_Space_Percent=CAST(Free_Space_GB*100/Total_Space_GB AS NUMERIC(18,2))
drop table if exists [dbo].[Temp_diskspace]
go
select * from [Data].[dbo].[T_diskspace]
go
这段代码每日运行即可
以上需要 SQLServer 2008 以上版本