Edit 2007-8-9:Added code to show database file sizes. Not really closely related to tables sizes, but a lot of the people who need this want to know why their database it so large, so it may help to know which files, especially the logs, are so large, and if the files have empty space in them.-- Script to analyze table space usage using the-- output from the sp_spaceused stored procedure-- Works with SQL 7.0, 2000, and 2005set nocount onprint 'Show Size, Space Used, Unused Space, Type, and Name of all database files'select [FileSizeMB] = convert(numeric(10,2),sum(round(a.size/128.,2))), [UsedSpaceMB] = convert(numeric(10,2),sum(round(fileproperty( a.name,'SpaceUsed')/128.,2))) , [UnusedSpaceMB] = convert(numeric(10,2),sum(round((a.size-fileproperty( a.name,'SpaceUsed'))/128.,2))) , [Type] = case when a.groupid is null then '' when a.groupid = 0 then 'Log' else 'Data' end, [DBFileName] = isnull(a.name,'*** Total for all files ***')from sysfiles agroup by groupid, a.name with rolluphaving a.groupid is null or a.name is not nullorder by case when a.groupid is null then 99 when a.groupid = 0 then 0 else 1 end, a.groupid, case when a.name is null then 99 else 0 end, a.namecreate table #TABLE_SPACE_WORK( TABLE_NAME sysname not null , TABLE_ROWS numeric(18,0) not null , RESERVED varchar(50) not null , DATA varchar(50) not null , INDEX_SIZE varchar(50) not null , UNUSED varchar(50) not null ,)create table #TABLE_SPACE_USED( Seq int not null identity(1,1) primary key clustered, TABLE_NAME sysname not null , TABLE_ROWS numeric(18,0) not null , RESERVED varchar(50) not null , DATA varchar(50) not null , INDEX_SIZE varchar(50) not null , UNUSED varchar(50) not null ,)create table #TABLE_SPACE( Seq int not null identity(1,1) primary key clustered, TABLE_NAME SYSNAME not null , TABLE_ROWS int not null , RESERVED int not null , DATA int not null , INDEX_SIZE int not null , UNUSED int not null , USED_MB numeric(18,4) not null, USED_GB numeric(18,4) not null, AVERAGE_BYTES_PER_ROW numeric(18,5) null, AVERAGE_DATA_BYTES_PER_ROW numeric(18,5) null, AVERAGE_INDEX_BYTES_PER_ROW numeric(18,5) null, AVERAGE_UNUSED_BYTES_PER_ROW numeric(18,5) null,)declare @fetch_status intdeclare @proc varchar(200)select @proc = rtrim(db_name())+'.dbo.sp_spaceused'declare Cur_Cursor cursor localforselect TABLE_NAME = rtrim(TABLE_SCHEMA)+'.'+rtrim(TABLE_NAME)from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'order by 1open Cur_Cursordeclare @TABLE_NAME varchar(200)select @fetch_status = 0while @fetch_status = 0 begin fetch next from Cur_Cursor into @TABLE_NAME select @fetch_status = @@fetch_status if @fetch_status <> 0 begin continue end truncate table #TABLE_SPACE_WORK insert into #TABLE_SPACE_WORK ( TABLE_NAME, TABLE_ROWS, RESERVED, DATA, INDEX_SIZE, UNUSED ) exec @proc @objname = @TABLE_NAME ,@updateusage = 'true' -- Needed to work with SQL 7 update #TABLE_SPACE_WORK set TABLE_NAME = @TABLE_NAME insert into #TABLE_SPACE_USED ( TABLE_NAME, TABLE_ROWS, RESERVED, DATA, INDEX_SIZE, UNUSED ) select TABLE_NAME, TABLE_ROWS, RESERVED, DATA, INDEX_SIZE, UNUSED from #TABLE_SPACE_WORK end --While endclose Cur_Cursordeallocate Cur_Cursorinsert into #TABLE_SPACE ( TABLE_NAME, TABLE_ROWS, RESERVED, DATA, INDEX_SIZE, UNUSED, USED_MB, USED_GB, AVERAGE_BYTES_PER_ROW, AVERAGE_DATA_BYTES_PER_ROW, AVERAGE_INDEX_BYTES_PER_ROW, AVERAGE_UNUSED_BYTES_PER_ROW )select TABLE_NAME, TABLE_ROWS, RESERVED, DATA, INDEX_SIZE, UNUSED, USED_MB = round(convert(numeric(25,10),RESERVED)/ convert(numeric(25,10),1024),4), USED_GB = round(convert(numeric(25,10),RESERVED)/ convert(numeric(25,10),1024*1024),4), AVERAGE_BYTES_PER_ROW = case when TABLE_ROWS <> 0 then round( (1024.000000*convert(numeric(25,10),RESERVED))/ convert(numeric(25,10),TABLE_ROWS),5) else null end, AVERAGE_DATA_BYTES_PER_ROW = case when TABLE_ROWS <> 0 then round( (1024.000000*convert(numeric(25,10),DATA))/ convert(numeric(25,10),TABLE_ROWS),5) else null end, AVERAGE_INDEX_BYTES_PER_ROW = case when TABLE_ROWS <> 0 then round( (1024.000000*convert(numeric(25,10),INDEX_SIZE))/ convert(numeric(25,10),TABLE_ROWS),5) else null end, AVERAGE_UNUSED_BYTES_PER_ROW = case when TABLE_ROWS <> 0 then round( (1024.000000*convert(numeric(25,10),UNUSED))/ convert(numeric(25,10),TABLE_ROWS),5) else null endfrom ( select TABLE_NAME, TABLE_ROWS, RESERVED = convert(int,rtrim(replace(RESERVED,'KB',''))), DATA = convert(int,rtrim(replace(DATA,'KB',''))), INDEX_SIZE = convert(int,rtrim(replace(INDEX_SIZE,'KB',''))), UNUSED = convert(int,rtrim(replace(UNUSED,'KB',''))) from #TABLE_SPACE_USED aa ) aorder by TABLE_NAMEprint 'Show results in descending order by size in MB'select * from #TABLE_SPACE order by USED_MB descgodrop table #TABLE_SPACE_WORKdrop table #TABLE_SPACE_USED drop table #TABLE_SPACE
CODO ERGO SUM