In SQL Server there are two stored procedures that help one to determine the size of a table. One is documented and more widely popular, the other is not. These two stored procedures are sp_spaceused and sp_MStablespace. Dugi wrote a blog article about the the two stored procedures in March of this year. I don’t intend to rehash what he has covered. What I intend is to look at the internals of the two stored procedures. This will be the first of a multi-part series.
I saw a question asking how to find the table sizes for all of the tables in a database. A few scripts were provided (one using sp_MStablespace and one using sp_spaceused). I had been using the msTablespace version for quite some time and had never questioned it’s accuracy. That changed when the question evolved into why do they (the two scripts) show the same results? So, I decided I needed to figure out what is happening inside both procedures to see if I could determine a reason for the difference. I will be comparing these on SQL Server 2008.
This stored procedure has been mostly updated to use the new DMVs available since SQL 2005. It currently relies heavily on sys.dm_db_partition_stats. This procedure determines the size of the indexes by subtracting the number of pages from the number of used pages. The idea here is that the number of Data Pages will be less than the total number of used pages. This stored procedure does still rely on a soon to be deprecated object called sysfiles. The replacement for that object would be sys.database_files. The functionality would be somewhat different, in regards to how it is used in this procedure – the results are the same. Despite that, this proc does not look to be on the replacement block any time soon.
This stored procedure on the contrary does look like it will be deprecated, though I was unable to find information to back that up. When delving into the procedure, one can quickly spot that it relies on sysindexes and sysobjects for much of its heavy lifting. The sizing information will be coming from sys.partitions, sys.allocation_units and sysindexes. This procedure uses sysindexes mostly for that sizing information and then calculates the data size based on clustered indexes and heaps. Then to calculate the remaining index size, it subtracts that size from the total for all of the indexes on the specified table. The math is a bit different and can be the reason for the difference. This procedure seems to be in need of a decent sized overhaul if expected to not be deprecated.
After looking at the code and then running some tests with each of these procedures, I was able to corroborate the claim that they don’t return the same results. With that in hand, I decided to take a stab at writing something different to help create a consistent return. Thus I will be sharing some queries I have been working on for each of these. The desired goal is that both would return the same results. Based on the consistency of information between the DMVs and the necessary (and some bonus) elements for these queries, that may be a bit more difficult to do. For the sp_MSTablespace query, the crux of the query will be the sys.dm_db_index_physical_stats function, while the sp_spaceused query may continue to rely on sys.dm_db_partition_stats or just sys.partitions. Both queries may rely on a combination of these latter two DMVs, tune in to find out.