The sp__diskdevice code from Ed Barlow was written 11 years and there are a number of issues that need addressing:
- Unnecessary use of temporary tables (#tablename) that can lead to lock contention in the system tables tempdb..sysobjects, tempdb..sysindexes, and tempdb..syscolumns.
- It doesn’t handle the logical page size (2k, 4k, 8k, 16k) in an intuitive manner.
For those of you that don’t know, the system variable @@pagesize is the physical page size, which is always 2K. The @@maxpagesize is the logical page size (2K, 4K, 8K, 16K). The column size in the master..sysusages table is specified in logical pages while the low and high columns of the master..sysdevices table is specified in physical pages.
Original Code:
/ * Procedure copyright(c) 1995 by Edward M Barlow */ /************************************************************************\ |* Procedure Name: diskdevice |* \************************************************************************/ :r database go :r dumpdb go if exists (select * from sysobjects where type = "P" and name = "sp__diskdevice_old") begin drop proc sp__diskdevice_old end go create procedure sp__diskdevice_old (@devname char(30)=NULL, @dont_format char(1)=null ) as declare @msg varchar(255) declare @numpgsmb float /* Number of Pages per Megabytes */ declare @tapeblocksize int set nocount on select @numpgsmb = (1048576. / v.low) from master.dbo.spt_values v where v.number = 1 and v.type = "E" create table #dev_tbl ( name char(30), phyname char(255), disk_size float null, status int null, disk_used float null, mirrored char(1) null ) insert #dev_tbl select name=d.name, phyname = d.phyname, disk_size=0, status=status, disk_used=0, mirrored=NULL from master.dbo.sysdevices d where name=isnull(@devname,name) /* Parallel */ update #dev_tbl set mirrored="P" where status & 64 = 64 /* Serial */ update #dev_tbl set mirrored="S" where status & 32 = 32 /* Disabled */ update #dev_tbl set mirrored="?" where status & 256 = 256 /* Confused */ update #dev_tbl set mirrored="?" where status & 32 = 32 and status & 512 != 512 /* Add in its size in MB. */ update #dev_tbl set disk_size = (1. + (d.high - d.low)) / @numpgsmb from master.dbo.sysdevices d, #dev_tbl where d.status & 2 = 2 and #dev_tbl.name = d.name update #dev_tbl set disk_used = ( select sum(size) from master.dbo.sysusages u, master.dbo.sysdevices d where d.status & 2 = 2 and vstart between low and high and #dev_tbl.name = d.name group by name ) / @numpgsmb update #dev_tbl set name=rtrim(name)+" ("+mirrored+")" where mirrored is not null /* if @devname is null begin if @dont_format is not null begin print "" print "****** PHYSICAL DISK DEVICES (Mirror info after device name) ******" end end */ update #dev_tbl set disk_used=0 where disk_used is null if @dont_format is not null select "Device Name"=name, "Physical Name"=phyname, size=str(disk_size,7,1)+"MB", alloc=str(disk_used,7,1)+"MB", free=str(disk_size-disk_used,7,1)+"MB" from #dev_tbl where status & 2 = 2 else select "Device Name"=substring(name,1,18), "Physical Name"=substring(phyname,1,31), size=str(disk_size,6,0)+"MB", alloc=str(disk_used,6,0)+"MB", free=str(disk_size-disk_used,6,0)+"MB" from #dev_tbl where status & 2 = 2 if @devname is not null begin if exists (select * from master.dbo.sysdatabases d, master.dbo.sysusages u, master.dbo.sysdevices dv where d.dbid = u.dbid and dv.low < = size + vstart and dv.high >= size + vstart - 1 and dv.status & 2 = 2 and dv.name=@devname ) begin select db_name=d.name, size = size / @numpgsmb, usage = convert(char(18),b.name) from master.dbo.sysdatabases d, master.dbo.sysusages u, master.dbo.sysdevices dv, master.dbo.spt_values b where d.dbid = u.dbid and dv.low < = size + vstart and dv.high >= size + vstart - 1 and dv.status & 2 = 2 and b.type = "S" and u.segmap & 7 = b.number and dv.name=@devname order by db_name,usage end else begin if @dont_format is not null print "****** Device Unused By Any Databases ******" end end return (0) go /* Give execute privilege to users. This can be removed if you only want the sa to have excute privilege on this stored proc */ grant exec on sp__diskdevice_old to public go exit
No more temp table code:
/* Procedure copyright(c) 1995 by Edward M Barlow */ /************************************************************************\ |* Procedure Name: diskdevice |* \************************************************************************/ :r database go :r dumpdb go if exists (select * from sysobjects where type = "P" and name = "sp__diskdevice") begin drop proc sp__diskdevice end go create procedure sp__diskdevice (@devname char(30)=NULL, @dont_format char(1)=null ) as declare @msg varchar(255) declare @numpgsmb float /* Number of Pages per Megabytes */ declare @tapeblocksize int set nocount on if @devname is null begin select d.name as "Device Name", d.phyname as "Physical Name" from master.dbo.sysdevices d where d.status & 2 != 2 end select case when (@dont_format is null) then substring(d.name, 1, 18) else d.name end as "Device Name", case when (@dont_format is not null) then substring(d.phyname, 1, 31) else d.phyname end as "Physical Name", convert(varchar(7), convert(int, ((1. + (d.high - d.low))*@@pagesize) / 1048576.) ) + "MB" as "size", convert(varchar(7), (select convert(int, sum(su.size) / (1024 / (@@maxpagesize/1024))) from master.dbo.sysusages su, master.dbo.sysdevices sd where sd.status & 2 = 2 and su.vstart between sd.low and sd.high and d.name = sd.name) ) + "MB" as "alloc", convert(varchar(7), convert(int, ( ((1. + (d.high - d.low))*@@pagesize) / 1048576.) - (select convert(int, sum(su.size) / (1024 / (@@maxpagesize/1024))) from master.dbo.sysusages su, master.dbo.sysdevices sd where sd.status & 2 = 2 and su.vstart between sd.low and sd.high and d.name = sd.name) ) ) + "MB" as "free" from master.dbo.sysdevices d where d.status & 2 = 2 and name=isnull(@devname,name) if @devname is not null begin if exists (select * from master.dbo.sysdatabases d, master.dbo.sysusages u, master.dbo.sysdevices dv where d.dbid = u.dbid and dv.low < = size + vstart and dv.high >= size + vstart - 1 and dv.status & 2 = 2 and dv.name=@devname ) begin select db_name=d.name, size = convert(int, u.size / (1024 / (@@maxpagesize/1024))), usage = convert(char(18),b.name) from master.dbo.sysdatabases d, master.dbo.sysusages u, master.dbo.sysdevices dv, master.dbo.spt_values b where d.dbid = u.dbid and dv.low < = size + vstart and dv.high >= size + vstart - 1 and dv.status & 2 = 2 and b.type = "S" and u.segmap & 7 = b.number and dv.name=@devname order by db_name,usage end else begin if @dont_format is not null print "****** Device Unused By Any Databases ******" end end return (0) go /* Give execute privilege to users. This can be removed if you only want the sa to have excute privilege on this stored proc */ grant exec on sp__diskdevice to public go exit