sp_spaceused is one of the system stored procedure used frequently by many DBA’s that reveals amount of space used by database/tables. This procedure can be executed either by passing parameters or no parameters. The objective of this stored procedure is to measure the amount of space consumed by database or tables.
This article demonstrates a simple process that saves database usage information in a single result set. This is a simulation of sp_spaceused using DMV’s. It gives db usage information of all dbs in a single result set also the output includes two more extra columns which tells data and log file size. You can also customize the code to capture db usage information for specific databases. The process is useful in monitoring DB growth over time and lets you see what databases are growing rapidly also help in estimating future growth and disk space requirements. The SQL output can be stored in a table which allows us to estimate future growth and helps in forecasting the disk space requirement over time. In some cases the results are not accurate and it requires update system views.
The most common usage for sp_spaceused is to measure the amount of spaced used for a database. In order to perform this, execute the procedure with no parameters
USE <DatabaseName>GOsp_spaceusedFor Example:- USE EMPLOYEEGOsp_spaceused
USE <
Database
Name
>
GO
sp_spaceused
For Example:- USE EMPLOYEEGOsp_spaceused
USE EMPLOYEE
If procedure is called with valid object, single result set is returned for the specific object and it displays the number of rows, disk space reserved, and disk space used by a table, indexed views.
USE <Database Name>GOsp_spaceused [[ @objname = ] 'objname' ] For Example:-
USE <Database Name>GOsp_spaceused [[ @objname = ] 'objname' ]
USE <Database Name>
sp_spaceused [[ @objname = ]
'objname'
]
'Production.ProductInventory'
The output gives db usage information of all dbs in a single result set also the output includes two more extra columns which gives data and log file sizes
--Displaying the usage details of all the databases.
DECLARE
@allocation_table
table
(
dbname sysname,
reservedpages
bigint
,
usedpages
pages
)
INSERT
INTO
EXEC
sp_MSforeachdb N
'IF EXISTS
SELECT 1 FROM SYS.DATABASES WHERE name = '
'?'
' AND NAME NOT IN('
'master'
','
'msdb'
'model'
'tempdb'
') and STATE=0
--customize to monitor specific databases
--SELECT 1 FROM SYS.DATABASES WHERE name = '
' AND NAME IN('
'EMPLOYEE'
BEGIN
SELECT
'
',
SUM(a.total_pages) as reservedpages,
SUM(a.used_pages) as usedpages,
SUM(
CASE
-- XML-Index and FT-Index internal tables are not considered "data", but is part of "index_size"
When it.internal_type IN (202,204,211,212,213,214,215,216) Then 0
When a.type <> 1 Then a.used_pages
When p.index_id < 2 Then a.data_pages
Else 0
END
) as pages
from ?.sys.partitions p join ?.sys.allocation_units a on p.partition_id = a.container_id
left join ?.sys.internal_tables it on p.object_id = it.object_id
END'
;
-- from first result set of 'exec sp_spacedused'
db_name(sf.database_id)
as
[database_name]
,ltrim(str((
convert
dec
(15,2),sf.dbsize) +
(15,2),sf.logsize)) * 8192 / 1048576,15,2) +
' MB'
[database_size]
case
when
sf.dbsize >= pages.reservedpages
then
(15,2),sf.dbsize) -
(15,2),pages.reservedpages))
* 8192 / 1048576
else
0
end
),15,2) +
[unallocated
space
-- from second result set of 'exec sp_spacedused'
,ltrim(str(pages.reservedpages * 8192 / 1024.,15,0) +
' KB'
[reserved]
,ltrim(str(pages.pages * 8192 / 1024.,15,0) +
data
,ltrim(str((pages.usedpages - pages.pages) * 8192 / 1024.,15,0) +
index_size
,ltrim(str((pages.reservedpages - pages.usedpages) * 8192 / 1024.,15,0) +
unused
-- additional columns data and Log Size
(15,2),sf.dbsize)) * 8192 / 1048576,15,2) +
dbsize
logsize
FROM
select
database_id,
sum
type = 0
size
))
dbsize,
type <> 0
from
sys.master_files
group
by
database_id
) sf,
dbname,
reservedpages,
usedpages,
@ALLOCATION_TABLE
) pages
WHERE
DB_NAME(sf.database_id)=pages.dbname
Change the below shown line from an above given code for any customization. For example, the code below ran against EMPLOYEE database also the below screen show comparison of outputs from DMV's v/s sp_spaceused
The database usage information that we gather contains guidelines to help you plan and configure the storage and SQL Server database This process defined in three steps
/****************************************************************************************************** The table tb_SpaceUsed is created to gather the details periodically ******************************************************************************************************/
CREATE
TABLE
tb_SpaceUsed
Database_Name sysname,
database_sizeMB
decimal
(7,2),
Unallocated_SpaceMB
reservedKB
dataKB
Index_SizeKB
unusedKB
dbSizeMB
logSizeMB
logdate
int
default
CONVERT
varchar
(10), getdate(),112))
/******************************************************************************************************
--@allocation_table variable is used to gather allocation units details of all the databases
******************************************************************************************************/
--Inserting the db usage information to tb_SpaceUsed table
tb_SpaceUsed(Database_Name,database_sizeMB,Unallocated_SpaceMB,reservedKB,dataKB,Index_SizeKB,unusedKB,dbSizeMB,logSizeMB)
(15,2),sf.logsize)) * 8192 / 1048576,15,2) )
),15,2) )
,ltrim(str(pages.reservedpages * 8192 / 1024.,15,0) )
,ltrim(str(pages.pages * 8192 / 1024.,15,0) )
,ltrim(str((pages.usedpages - pages.pages) * 8192 / 1024.,15,0) )
,ltrim(str((pages.reservedpages - pages.usedpages) * 8192 / 1024.,15,0) )
(15,2),sf.dbsize)) * 8192 / 1048576,15,2) )
(15,2),sf.logsize)) * 8192 / 1048576,15,2))
*
/*
Create
temp
TABLEs before
any
DML
to
ensure
dynamic
We need
a
do the calculation.
reserved:
(reserved)
indid
in
(0, 1, 255)
DATA:
(dpages)
indid < 2 +
(used)
indid = 255 (text)
indexp:
(0, 1, 255) - DATA
unused:
(reserved) -
*/
---------------------------------------------------------------------------------------------------
-- Desc. : created a automated script to log's all space details of different database.
@pages
INT
@dbname sysname
@dbsize
DEC
(15,0)
@logsize
(15)
@bytesperpage
@pagesperMB
@DML1 nvarchar(2000)
@DML2 nvarchar(200)
@DML3 nvarchar(200)
@DML4 nvarchar(200)
@DML5 nvarchar(200)
@DML6 nvarchar(200)
@DML7 nvarchar(200)
@DML8 nvarchar(200)
@DML9 nvarchar(200)
@DML10 nvarchar(200)
@DML11 nvarchar(200)
@DML12 nvarchar(1000)
@DML13 nvarchar(4000)
@LoopStatus
@RowId
@dbname_1
(100)
@DML14
(2000)
SET
@DML14='
,@dbname sysname,@dbsize
(15,0),@logsize
(15),@bytesperpage
(15,0),@pagesperMB
(15,0),
@DML1 nvarchar(2000),@DML2 nvarchar(200),@DML3 nvarchar(200),@DML4 nvarchar(200),@DML5 nvarchar(200),@DML6 nvarchar(200),
@DML7 nvarchar(200),@DML8 nvarchar(200),@DML9 nvarchar(200),@DML10 nvarchar(200),@DML11 nvarchar(200),@DML12 nvarchar(800),
@DML13 nvarchar(2000),@LoopStatus
,@RowId
,@dbname_1
CREATE TABLE #growthRate
SlNo int identity(1,1) primary key,
DatabaseName varchar(25),
Databasesize DECIMAL(10,2),
UnallocatedSpace DECIMAL(10,2),
Reserved INT,
Data INT,
Indexsize INT,
unused INT
CREATE TABLE #spt_space
rows INT NULL,
reserved DEC(15) NULL,
DATA DEC(15) NULL,
indexp DEC(15) NULL,
unused DEC(15) NULL
CREATE TABLE #Database_List
id int identity(1,1) PRIMARY KEY,
DatabaseName VARCHAR(200)
INSERT INTO #Database_List VALUES('
pubs
')
Load
Hist
--INSERT INTO #Database_List VALUES('
Tempdb
SET @dbsize=1
SET @logsize=1
SET @bytesperpage=1
SET @pagesperMB=1
SET @pages=1
SET @LoopStatus=1
SET @RowId=1
WHILE( @LoopStatus<>0)
SELECT @dbname_1=DatabaseName FROM #Database_List WHERE id=@RowId
IF @@ROWCOUNT=0
SET @LoopStatus=0
ELSE
TRUNCATE TABLE #spt_space
SET @DML2='
@dbsize =
(15),
dbo.sysfiles
(status & 64 = 0)
'+CHAR(13)
SET @DML3='
@logsize =
(status & 64 <> 0)
SET @DML4='
@bytesperpage = low
master.dbo.spt_values
number = 1
and
type =
''
E
SET @DML5='
@pagesperMB = 1048576 / @bytesperpage
'+char(13)
SET @DML6='
#spt_space (reserved)
(15),reserved))
sysindexes
SET @DML7='
@pages =
(15),dpages))
indid < 2
SET @DML8='
@pages = @pages +
ISNULL
(15),used)), 0)
indid = 255
SET @DML9='
UPDATE
#spt_space
DATA =@pages
SET @DML10='
indexp = (
(15),used))
(0, 1, 255)) - DATA
SET @DML11='
unused = reserved - (
(0, 1, 255))
SET @DML12='
#growthRate(DatabaseName,Databasesize ,UnallocatedSpace,Reserved,Data,Indexsize,unused)
DatabaseName = db_name(),
DatabaseSize = ltrim(str((@dbsize + @logsize) / @pagesperMB,15,2)),
unallocatedspace = ltrim(str((@dbsize - (
(0, 1, 255))) / @pagesperMB,15,2)),
Reserved = ltrim(str(reserved * d.low / 1024,15,0)),
Data = ltrim(str(DATA * d.low / 1024,15,0)),
IndexSize = ltrim(str(indexp * d.low / 1024,15,0)),
Unused = ltrim(str(unused * d.low / 1024,15,0))
#spt_space, master.dbo.spt_values d
d.number = 1
AND
d.type =
SET @DML1='
USE
'+'
'+@dbname_1+
char
(13)+
(13)+@DML14+
Char
(13)
@DML13=@DML1+@DML2+@DML3+@DML4+@DML5+@DML6+@DML7+@DML8+@DML9+@DML10+@DML11+@DML12
sp_executesql @DML13
@RowId=@RowId+1
#growthRate
DROP
#Database_List
Displaying all user defined table usage information
USE <DBNAME>
@PageSize
float
@PageSize=v.low/1024.0
master.dbo.spt_values v
where
v.number=1
v.type=
'E'
object_Name(i.object_id)
[
name
,p.
rows
Convert
(50),@PageSize *
SUM
(total_pages)) +
WHEN
a.type <> 1
THEN
a.used_pages
p.index_id < 2
a.data_pages
)) +
[data]
(a.used_pages -
[index_size]
(total_pages-used_pages)) +
[unused]
sys.indexes
i
JOIN
sys.partitions
p
ON
p.object_id = i.object_id
p.index_id = i.index_id
sys.allocation_units
a.container_id = p.partition_id
sys.tables t
i.object_id=t.object_id
Where
i.type<=1
a.type=1
t.type=
'U'
is_ms_shipped=0
GROUP
BY
i.object_id,p.
Prash Can you remove the images and take screenshot again and upload it the images are not clear. The last two images are not good as query is selected and its all in blue make sure queries are visible
thanks
I've uploaded the new images.Thanks again Shanky.