Disks image

sp_drivespace – See How Much Space You Have On Your Disks, Including Mount Points

,

We love xp_fixeddrives here, it’s a quick and simple way to see how much space you’ve got available on your drives. But there are just a couple of things that I really wish it would do better.

Firstly, I’d love to see the total size of the drive and possibly even a percentage of free space left.

Secondly, mount points. If you’ve got any databases that are on mount points, it’s not going to give you any idea of what you’ve got left on there.

This is the reason that I put together sp_drivespace. The following procedure uses dm_os_volume_stats, which will give us all the information that we’re missing in a simple to run procedure.

The query against dm_os_volume_stats was written by Adrian Buckman and has been pinched from the latest release of our Undercover Inspector.

Parameters

The proc has the following parameters

@xp_fixeddrivesCompat – Switching this to 1 will format the output of the procedure to match xp_fixeddrives. Useful if you’re using xp_fixeddrives and want a drop in replacement that’ll cover your mount points. Default value is 0.

@unit – Defines the unit of storage that will be output, BYTE, KB, MB, TB or GB. The default value is GB. This parameter is ignored if @xp_fixeddrivesCompat is on.

Code

The code can be found below or on our Git Hub site.

https://github.com/SQLUndercover/UndercoverToolbox/blob/master/sp_drivespace.sql

/******************************************************************
Author: David Fowler
Revision date: 3 July 2019
Version: 1
© www.sqlundercover.com 

This script is for personal, educational, and internal 
corporate purposes, provided that this header is preserved. Redistribution or sale 
of this script,in whole or in part, is prohibited without the author's express 
written consent. 
The software is provided "as is", without warranty of any kind, express or
implied, including but not limited to the warranties of merchantability,
fitness for a particular purpose and noninfringement. in no event shall the
authors or copyright holders be liable for any claim, damages or other
liability, whether in an action of contract, tort or otherwise, arising from,
out of or in connection with the software or the use or other dealings in the
software.
******************************************************************/USE master
GO
CREATE PROC sp_drivespace
@xp_fixeddrivesCompat BIT = 0,  --return results matching the format of xp_fixeddrives, allows use as a drop in replacement for xp_fixeddrives
@unit VARCHAR(4) = 'GB' --BYTE, KB, MB, GB or TB - ignored if @xp_fixeddrivesCompat = 1
AS
BEGIN
IF OBJECT_ID('tempdb..#driveinfo') IS NOT NULL
DROP TABLE #driveinfo
--check for valid unit value
IF @unit NOT IN ('BYTE','KB','MB','TB','GB')
RAISERROR (N'Invalid Unit Specified, Must Be BYTE, KB, MB, GB or TB' , 15, 1)
--set divisor, to be used when converting units
DECLARE @divisor BIGINT
SELECT @divisor =CASE @unit
WHEN 'BYTE' THEN 1
WHEN 'KB' THEN 1024
WHEN 'MB' THEN POWER(1024,2)
WHEN 'GB' THEN POWER(1024,3)
WHEN 'TB' THEN POWER(CAST(1024 AS BIGINT),4)
END
CREATE TABLE #driveinfo
(volume_mount_point NVARCHAR(512),
available_bytes BIGINT,
total_bytes BIGINT,
logical_volume_name NVARCHAR(512))

--DistinctDrives derived table updated to show all database_id and file_id combinations grouped by file path.
--Row number is applied so that we can filter just one database_id and file_id combination per file path and then these 
--combinations are passed to the sys.dm_os_volume_stats system TVF , the reason for the filtering within the derived table is
--to reduce the number of executions performed by the TVF because on instances with lots of databases this can slow execution.
INSERT INTO #driveinfo (volume_mount_point,available_bytes,total_bytes,logical_volume_name)
SELECT DISTINCT
volumestats.volume_mount_point,
volumestats.available_bytes,
volumestats.total_bytes,
logical_volume_name
FROM 
(
SELECT 
[database_id],
[file_id],
ROW_NUMBER() OVER (PARTITION BY SUBSTRING(physical_name,1,LEN(physical_name)-CHARINDEX('',REVERSE(physical_name))+1) 
ORDER BY SUBSTRING(physical_name,1,LEN(physical_name)-CHARINDEX('',REVERSE(physical_name))+1) ASC) AS RowNum
FROM sys.master_files
WHERE database_id IN (SELECT database_id FROM sys.databases WHERE state = 0)
) DistinctDrives
CROSS APPLY sys.dm_os_volume_stats([DistinctDrives].[database_id],[DistinctDrives].[file_id]) volumestats
WHERE DistinctDrives.RowNum = 1

IF (@xp_fixeddrivesCompat = 1)
BEGIN
--if @xp_fixeddrivesCompat, return results matching the format of xp_fixeddrives
SELECT volume_mount_point, available_bytes / 1024 / 1024 AS [MB free]
FROM #driveinfo
END
ELSE
BEGIN
SELECTvolume_mount_point,
CAST(CAST(available_bytes AS DECIMAL(20,2)) / @divisor AS DECIMAL(20,2)) AS Available,
CAST(CAST(total_bytes AS DECIMAL(20,2)) / @divisor AS DECIMAL(20,2)) AS Total,
CAST(available_bytes AS DECIMAL(20,2))/CAST(total_bytes AS DECIMAL(20,2)) * 100  AS PercentFree
FROM #driveinfo
END
END

Original post (opens in new tab)
View comments in original post (opens in new tab)

Rate

5 (1)

You rated this post out of 5. Change rating

Share

Share

Rate

5 (1)

You rated this post out of 5. Change rating